Support Role-Based Access Control (#18425)

Signed-off-by: SimFG <bang.fu@zilliz.com>
pull/18528/head
SimFG 2022-08-04 11:04:34 +08:00 committed by GitHub
parent 4aab6ddaa7
commit ff0200210a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 5402 additions and 1837 deletions

5
go.mod
View File

@ -12,6 +12,8 @@ require (
github.com/apache/arrow/go/v8 v8.0.0-20220322092137-778b1772fd20
github.com/apache/pulsar-client-go v0.6.1-0.20210728062540-29414db801a7
github.com/bits-and-blooms/bloom/v3 v3.0.1
github.com/casbin/casbin/v2 v2.44.2
github.com/casbin/json-adapter/v2 v2.0.0
github.com/confluentinc/confluent-kafka-go v1.9.1
github.com/containerd/cgroups v1.0.2
github.com/gin-gonic/gin v1.7.7
@ -49,6 +51,7 @@ require (
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/grpc v1.46.0
google.golang.org/grpc/examples v0.0.0-20220617181431-3e7b97febc7f
google.golang.org/protobuf v1.28.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
stathat.com/c/consistent v1.0.0
)
@ -60,6 +63,7 @@ require (
github.com/AthenZ/athenz v1.10.15 // indirect
github.com/DataDog/zstd v1.4.6-0.20210211175136-c6db21d202f4 // indirect
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/apache/pulsar-client-go/oauth2 v0.0.0-20211108044248-fe3b7c4e445b // indirect
github.com/ardielle/ardielle-go v1.5.2 // indirect
@ -172,7 +176,6 @@ require (
gonum.org/v1/gonum v0.9.3 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220503193339-ba3ae3f07e29 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

9
go.sum
View File

@ -59,6 +59,8 @@ github.com/HdrHistogram/hdrhistogram-go v1.0.1 h1:GX8GAYDuhlFQnI2fRDHQhTlkHMz8bE
github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
@ -109,6 +111,11 @@ github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY=
github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8=
github.com/casbin/casbin/v2 v2.0.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/casbin/casbin/v2 v2.44.2 h1:mlWtgbX872r707frOq+REaHzfvsl+qQw0Eq+ekzJ7J8=
github.com/casbin/casbin/v2 v2.44.2/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/casbin/json-adapter/v2 v2.0.0 h1:nOCN3TK1CJKSNQQ/MnakbU9/cUcNR3N0AxBDnEBLSDI=
github.com/casbin/json-adapter/v2 v2.0.0/go.mod h1:LvsfPXXr8CD0ZFucAxawcY9Xb0FtLk3mozJ1qcSTUD4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
@ -1160,6 +1167,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183/go.mod h1:FvqrFXt+jCsyQibeRv4xxEJBL5iG2DDW5aeJwzDiq4A=

View File

@ -305,9 +305,9 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_common_2eproto::offsets[] PROT
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, resource_type_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, resource_privilege_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, resource_name_index_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, object_type_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, object_privilege_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::common::PrivilegeExt, object_name_index_),
};
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
{ 0, -1, sizeof(::milvus::proto::common::Status)},
@ -356,106 +356,107 @@ const char descriptor_table_protodef_common_2eproto[] PROTOBUF_SECTION_VARIABLE(
"*\n\004base\030\001 \001(\0132\034.milvus.proto.common.MsgB"
"ase\"M\n\014DMLMsgHeader\022*\n\004base\030\001 \001(\0132\034.milv"
"us.proto.common.MsgBase\022\021\n\tshardName\030\002 \001"
"(\t\"\251\001\n\014PrivilegeExt\0228\n\rresource_type\030\001 \001"
"(\0162!.milvus.proto.common.ResourceType\022B\n"
"\022resource_privilege\030\002 \001(\0162&.milvus.proto"
".common.ResourcePrivilege\022\033\n\023resource_na"
"me_index\030\003 \001(\005*\323\010\n\tErrorCode\022\013\n\007Success\020"
"\000\022\023\n\017UnexpectedError\020\001\022\021\n\rConnectFailed\020"
"\002\022\024\n\020PermissionDenied\020\003\022\027\n\023CollectionNot"
"Exists\020\004\022\023\n\017IllegalArgument\020\005\022\024\n\020Illegal"
"Dimension\020\007\022\024\n\020IllegalIndexType\020\010\022\031\n\025Ill"
"egalCollectionName\020\t\022\017\n\013IllegalTOPK\020\n\022\024\n"
"\020IllegalRowRecord\020\013\022\023\n\017IllegalVectorID\020\014"
"\022\027\n\023IllegalSearchResult\020\r\022\020\n\014FileNotFoun"
"d\020\016\022\016\n\nMetaFailed\020\017\022\017\n\013CacheFailed\020\020\022\026\n\022"
"CannotCreateFolder\020\021\022\024\n\020CannotCreateFile"
"\020\022\022\026\n\022CannotDeleteFolder\020\023\022\024\n\020CannotDele"
"teFile\020\024\022\023\n\017BuildIndexError\020\025\022\020\n\014Illegal"
"NLIST\020\026\022\025\n\021IllegalMetricType\020\027\022\017\n\013OutOfM"
"emory\020\030\022\021\n\rIndexNotExist\020\031\022\023\n\017EmptyColle"
"ction\020\032\022\033\n\027UpdateImportTaskFailure\020\033\022\032\n\026"
"CollectionNameNotFound\020\034\022\033\n\027CreateCreden"
"tialFailure\020\035\022\033\n\027UpdateCredentialFailure"
"\020\036\022\033\n\027DeleteCredentialFailure\020\037\022\030\n\024GetCr"
"edentialFailure\020 \022\030\n\024ListCredUsersFailur"
"e\020!\022\022\n\016GetUserFailure\020\"\022\025\n\021CreateRoleFai"
"lure\020#\022\023\n\017DropRoleFailure\020$\022\032\n\026OperateUs"
"erRoleFailure\020%\022\025\n\021SelectRoleFailure\020&\022\025"
"\n\021SelectUserFailure\020\'\022\031\n\025SelectResourceF"
"ailure\020(\022\033\n\027OperatePrivilegeFailure\020)\022\026\n"
"\022SelectGrantFailure\020*\022!\n\035RefreshPolicyIn"
"foCacheFailure\020+\022\025\n\021ListPolicyFailure\020,\022"
"\022\n\016NotShardLeader\020-\022\026\n\022NoReplicaAvailabl"
"e\020.\022\023\n\017SegmentNotFound\020/\022\022\n\rDDRequestRac"
"e\020\350\007*X\n\nIndexState\022\022\n\016IndexStateNone\020\000\022\014"
"\n\010Unissued\020\001\022\016\n\nInProgress\020\002\022\014\n\010Finished"
"\020\003\022\n\n\006Failed\020\004*\202\001\n\014SegmentState\022\024\n\020Segme"
"ntStateNone\020\000\022\014\n\010NotExist\020\001\022\013\n\007Growing\020\002"
"\022\n\n\006Sealed\020\003\022\013\n\007Flushed\020\004\022\014\n\010Flushing\020\005\022"
"\013\n\007Dropped\020\006\022\r\n\tImporting\020\007*>\n\017Placehold"
"erType\022\010\n\004None\020\000\022\020\n\014BinaryVector\020d\022\017\n\013Fl"
"oatVector\020e*\266\014\n\007MsgType\022\r\n\tUndefined\020\000\022\024"
"\n\020CreateCollection\020d\022\022\n\016DropCollection\020e"
"\022\021\n\rHasCollection\020f\022\026\n\022DescribeCollectio"
"n\020g\022\023\n\017ShowCollections\020h\022\024\n\020GetSystemCon"
"figs\020i\022\022\n\016LoadCollection\020j\022\025\n\021ReleaseCol"
"lection\020k\022\017\n\013CreateAlias\020l\022\r\n\tDropAlias\020"
"m\022\016\n\nAlterAlias\020n\022\024\n\017CreatePartition\020\310\001\022"
"\022\n\rDropPartition\020\311\001\022\021\n\014HasPartition\020\312\001\022\026"
"\n\021DescribePartition\020\313\001\022\023\n\016ShowPartitions"
"\020\314\001\022\023\n\016LoadPartitions\020\315\001\022\026\n\021ReleaseParti"
"tions\020\316\001\022\021\n\014ShowSegments\020\372\001\022\024\n\017DescribeS"
"egment\020\373\001\022\021\n\014LoadSegments\020\374\001\022\024\n\017ReleaseS"
"egments\020\375\001\022\024\n\017HandoffSegments\020\376\001\022\030\n\023Load"
"BalanceSegments\020\377\001\022\025\n\020DescribeSegments\020\200"
"\002\022\020\n\013CreateIndex\020\254\002\022\022\n\rDescribeIndex\020\255\002\022"
"\016\n\tDropIndex\020\256\002\022\013\n\006Insert\020\220\003\022\013\n\006Delete\020\221"
"\003\022\n\n\005Flush\020\222\003\022\027\n\022ResendSegmentStats\020\223\003\022\013"
"\n\006Search\020\364\003\022\021\n\014SearchResult\020\365\003\022\022\n\rGetInd"
"exState\020\366\003\022\032\n\025GetIndexBuildProgress\020\367\003\022\034"
"\n\027GetCollectionStatistics\020\370\003\022\033\n\026GetParti"
"tionStatistics\020\371\003\022\r\n\010Retrieve\020\372\003\022\023\n\016Retr"
"ieveResult\020\373\003\022\024\n\017WatchDmChannels\020\374\003\022\025\n\020R"
"emoveDmChannels\020\375\003\022\027\n\022WatchQueryChannels"
"\020\376\003\022\030\n\023RemoveQueryChannels\020\377\003\022\035\n\030SealedS"
"egmentsChangeInfo\020\200\004\022\027\n\022WatchDeltaChanne"
"ls\020\201\004\022\024\n\017GetShardLeaders\020\202\004\022\020\n\013GetReplic"
"as\020\203\004\022\020\n\013SegmentInfo\020\330\004\022\017\n\nSystemInfo\020\331\004"
"\022\024\n\017GetRecoveryInfo\020\332\004\022\024\n\017GetSegmentStat"
"e\020\333\004\022\r\n\010TimeTick\020\260\t\022\023\n\016QueryNodeStats\020\261\t"
"\022\016\n\tLoadIndex\020\262\t\022\016\n\tRequestID\020\263\t\022\017\n\nRequ"
"estTSO\020\264\t\022\024\n\017AllocateSegment\020\265\t\022\026\n\021Segme"
"ntStatistics\020\266\t\022\025\n\020SegmentFlushDone\020\267\t\022\017"
"\n\nDataNodeTt\020\270\t\022\025\n\020CreateCredential\020\334\013\022\022"
"\n\rGetCredential\020\335\013\022\025\n\020DeleteCredential\020\336"
"\013\022\025\n\020UpdateCredential\020\337\013\022\026\n\021ListCredUser"
"names\020\340\013\022\017\n\nCreateRole\020\300\014\022\r\n\010DropRole\020\301\014"
"\022\024\n\017OperateUserRole\020\302\014\022\017\n\nSelectRole\020\303\014\022"
"\017\n\nSelectUser\020\304\014\022\023\n\016SelectResource\020\305\014\022\025\n"
"\020OperatePrivilege\020\306\014\022\020\n\013SelectGrant\020\307\014\022\033"
"\n\026RefreshPolicyInfoCache\020\310\014\022\017\n\nListPolic"
"y\020\311\014*\"\n\007DslType\022\007\n\003Dsl\020\000\022\016\n\nBoolExprV1\020\001"
"*B\n\017CompactionState\022\021\n\rUndefiedState\020\000\022\r"
"\n\tExecuting\020\001\022\r\n\tCompleted\020\002*X\n\020Consiste"
"ncyLevel\022\n\n\006Strong\020\000\022\013\n\007Session\020\001\022\013\n\007Bou"
"nded\020\002\022\016\n\nEventually\020\003\022\016\n\nCustomized\020\004*\257"
"\001\n\013ImportState\022\021\n\rImportPending\020\000\022\020\n\014Imp"
"ortFailed\020\001\022\021\n\rImportStarted\020\002\022\024\n\020Import"
"Downloaded\020\003\022\020\n\014ImportParsed\020\004\022\023\n\017Import"
"Persisted\020\005\022\023\n\017ImportCompleted\020\006\022\026\n\022Impo"
"rtAllocSegment\020\n*\036\n\014ResourceType\022\016\n\nColl"
"ection\020\000*\335\001\n\021ResourcePrivilege\022\020\n\014Privil"
"egeAll\020\000\022\023\n\017PrivilegeCreate\020\001\022\021\n\rPrivile"
"geDrop\020\002\022\022\n\016PrivilegeAlter\020\003\022\021\n\rPrivileg"
"eRead\020\004\022\021\n\rPrivilegeLoad\020\005\022\024\n\020PrivilegeR"
"elease\020\006\022\024\n\020PrivilegeCompact\020\007\022\023\n\017Privil"
"egeInsert\020\010\022\023\n\017PrivilegeDelete\020\t:^\n\021priv"
"ilege_ext_obj\022\037.google.protobuf.MessageO"
"ptions\030\351\007 \001(\0132!.milvus.proto.common.Priv"
"ilegeExtBW\n\016io.milvus.grpcB\013CommonProtoP"
"\001Z3github.com/milvus-io/milvus/internal/"
"proto/commonpb\240\001\001b\006proto3"
"(\t\"\237\001\n\014PrivilegeExt\0224\n\013object_type\030\001 \001(\016"
"2\037.milvus.proto.common.ObjectType\022>\n\020obj"
"ect_privilege\030\002 \001(\0162$.milvus.proto.commo"
"n.ObjectPrivilege\022\031\n\021object_name_index\030\003"
" \001(\005*\323\010\n\tErrorCode\022\013\n\007Success\020\000\022\023\n\017Unexp"
"ectedError\020\001\022\021\n\rConnectFailed\020\002\022\024\n\020Permi"
"ssionDenied\020\003\022\027\n\023CollectionNotExists\020\004\022\023"
"\n\017IllegalArgument\020\005\022\024\n\020IllegalDimension\020"
"\007\022\024\n\020IllegalIndexType\020\010\022\031\n\025IllegalCollec"
"tionName\020\t\022\017\n\013IllegalTOPK\020\n\022\024\n\020IllegalRo"
"wRecord\020\013\022\023\n\017IllegalVectorID\020\014\022\027\n\023Illega"
"lSearchResult\020\r\022\020\n\014FileNotFound\020\016\022\016\n\nMet"
"aFailed\020\017\022\017\n\013CacheFailed\020\020\022\026\n\022CannotCrea"
"teFolder\020\021\022\024\n\020CannotCreateFile\020\022\022\026\n\022Cann"
"otDeleteFolder\020\023\022\024\n\020CannotDeleteFile\020\024\022\023"
"\n\017BuildIndexError\020\025\022\020\n\014IllegalNLIST\020\026\022\025\n"
"\021IllegalMetricType\020\027\022\017\n\013OutOfMemory\020\030\022\021\n"
"\rIndexNotExist\020\031\022\023\n\017EmptyCollection\020\032\022\033\n"
"\027UpdateImportTaskFailure\020\033\022\032\n\026Collection"
"NameNotFound\020\034\022\033\n\027CreateCredentialFailur"
"e\020\035\022\033\n\027UpdateCredentialFailure\020\036\022\033\n\027Dele"
"teCredentialFailure\020\037\022\030\n\024GetCredentialFa"
"ilure\020 \022\030\n\024ListCredUsersFailure\020!\022\022\n\016Get"
"UserFailure\020\"\022\025\n\021CreateRoleFailure\020#\022\023\n\017"
"DropRoleFailure\020$\022\032\n\026OperateUserRoleFail"
"ure\020%\022\025\n\021SelectRoleFailure\020&\022\025\n\021SelectUs"
"erFailure\020\'\022\031\n\025SelectResourceFailure\020(\022\033"
"\n\027OperatePrivilegeFailure\020)\022\026\n\022SelectGra"
"ntFailure\020*\022!\n\035RefreshPolicyInfoCacheFai"
"lure\020+\022\025\n\021ListPolicyFailure\020,\022\022\n\016NotShar"
"dLeader\020-\022\026\n\022NoReplicaAvailable\020.\022\023\n\017Seg"
"mentNotFound\020/\022\022\n\rDDRequestRace\020\350\007*X\n\nIn"
"dexState\022\022\n\016IndexStateNone\020\000\022\014\n\010Unissued"
"\020\001\022\016\n\nInProgress\020\002\022\014\n\010Finished\020\003\022\n\n\006Fail"
"ed\020\004*\202\001\n\014SegmentState\022\024\n\020SegmentStateNon"
"e\020\000\022\014\n\010NotExist\020\001\022\013\n\007Growing\020\002\022\n\n\006Sealed"
"\020\003\022\013\n\007Flushed\020\004\022\014\n\010Flushing\020\005\022\013\n\007Dropped"
"\020\006\022\r\n\tImporting\020\007*>\n\017PlaceholderType\022\010\n\004"
"None\020\000\022\020\n\014BinaryVector\020d\022\017\n\013FloatVector\020"
"e*\266\014\n\007MsgType\022\r\n\tUndefined\020\000\022\024\n\020CreateCo"
"llection\020d\022\022\n\016DropCollection\020e\022\021\n\rHasCol"
"lection\020f\022\026\n\022DescribeCollection\020g\022\023\n\017Sho"
"wCollections\020h\022\024\n\020GetSystemConfigs\020i\022\022\n\016"
"LoadCollection\020j\022\025\n\021ReleaseCollection\020k\022"
"\017\n\013CreateAlias\020l\022\r\n\tDropAlias\020m\022\016\n\nAlter"
"Alias\020n\022\024\n\017CreatePartition\020\310\001\022\022\n\rDropPar"
"tition\020\311\001\022\021\n\014HasPartition\020\312\001\022\026\n\021Describe"
"Partition\020\313\001\022\023\n\016ShowPartitions\020\314\001\022\023\n\016Loa"
"dPartitions\020\315\001\022\026\n\021ReleasePartitions\020\316\001\022\021"
"\n\014ShowSegments\020\372\001\022\024\n\017DescribeSegment\020\373\001\022"
"\021\n\014LoadSegments\020\374\001\022\024\n\017ReleaseSegments\020\375\001"
"\022\024\n\017HandoffSegments\020\376\001\022\030\n\023LoadBalanceSeg"
"ments\020\377\001\022\025\n\020DescribeSegments\020\200\002\022\020\n\013Creat"
"eIndex\020\254\002\022\022\n\rDescribeIndex\020\255\002\022\016\n\tDropInd"
"ex\020\256\002\022\013\n\006Insert\020\220\003\022\013\n\006Delete\020\221\003\022\n\n\005Flush"
"\020\222\003\022\027\n\022ResendSegmentStats\020\223\003\022\013\n\006Search\020\364"
"\003\022\021\n\014SearchResult\020\365\003\022\022\n\rGetIndexState\020\366\003"
"\022\032\n\025GetIndexBuildProgress\020\367\003\022\034\n\027GetColle"
"ctionStatistics\020\370\003\022\033\n\026GetPartitionStatis"
"tics\020\371\003\022\r\n\010Retrieve\020\372\003\022\023\n\016RetrieveResult"
"\020\373\003\022\024\n\017WatchDmChannels\020\374\003\022\025\n\020RemoveDmCha"
"nnels\020\375\003\022\027\n\022WatchQueryChannels\020\376\003\022\030\n\023Rem"
"oveQueryChannels\020\377\003\022\035\n\030SealedSegmentsCha"
"ngeInfo\020\200\004\022\027\n\022WatchDeltaChannels\020\201\004\022\024\n\017G"
"etShardLeaders\020\202\004\022\020\n\013GetReplicas\020\203\004\022\020\n\013S"
"egmentInfo\020\330\004\022\017\n\nSystemInfo\020\331\004\022\024\n\017GetRec"
"overyInfo\020\332\004\022\024\n\017GetSegmentState\020\333\004\022\r\n\010Ti"
"meTick\020\260\t\022\023\n\016QueryNodeStats\020\261\t\022\016\n\tLoadIn"
"dex\020\262\t\022\016\n\tRequestID\020\263\t\022\017\n\nRequestTSO\020\264\t\022"
"\024\n\017AllocateSegment\020\265\t\022\026\n\021SegmentStatisti"
"cs\020\266\t\022\025\n\020SegmentFlushDone\020\267\t\022\017\n\nDataNode"
"Tt\020\270\t\022\025\n\020CreateCredential\020\334\013\022\022\n\rGetCrede"
"ntial\020\335\013\022\025\n\020DeleteCredential\020\336\013\022\025\n\020Updat"
"eCredential\020\337\013\022\026\n\021ListCredUsernames\020\340\013\022\017"
"\n\nCreateRole\020\300\014\022\r\n\010DropRole\020\301\014\022\024\n\017Operat"
"eUserRole\020\302\014\022\017\n\nSelectRole\020\303\014\022\017\n\nSelectU"
"ser\020\304\014\022\023\n\016SelectResource\020\305\014\022\025\n\020OperatePr"
"ivilege\020\306\014\022\020\n\013SelectGrant\020\307\014\022\033\n\026RefreshP"
"olicyInfoCache\020\310\014\022\017\n\nListPolicy\020\311\014*\"\n\007Ds"
"lType\022\007\n\003Dsl\020\000\022\016\n\nBoolExprV1\020\001*B\n\017Compac"
"tionState\022\021\n\rUndefiedState\020\000\022\r\n\tExecutin"
"g\020\001\022\r\n\tCompleted\020\002*X\n\020ConsistencyLevel\022\n"
"\n\006Strong\020\000\022\013\n\007Session\020\001\022\013\n\007Bounded\020\002\022\016\n\n"
"Eventually\020\003\022\016\n\nCustomized\020\004*\257\001\n\013ImportS"
"tate\022\021\n\rImportPending\020\000\022\020\n\014ImportFailed\020"
"\001\022\021\n\rImportStarted\020\002\022\024\n\020ImportDownloaded"
"\020\003\022\020\n\014ImportParsed\020\004\022\023\n\017ImportPersisted\020"
"\005\022\023\n\017ImportCompleted\020\006\022\026\n\022ImportAllocSeg"
"ment\020\n*(\n\nObjectType\022\016\n\nCollection\020\000\022\n\n\006"
"Global\020\001*\212\002\n\017ObjectPrivilege\022\020\n\014Privileg"
"eAll\020\000\022\035\n\031PrivilegeCreateCollection\020\001\022\033\n"
"\027PrivilegeDropCollection\020\002\022\037\n\033PrivilegeD"
"escribeCollection\020\003\022\034\n\030PrivilegeShowColl"
"ections\020\004\022\021\n\rPrivilegeLoad\020\005\022\024\n\020Privileg"
"eRelease\020\006\022\027\n\023PrivilegeCompaction\020\007\022\023\n\017P"
"rivilegeInsert\020\010\022\023\n\017PrivilegeDelete\020\t:^\n"
"\021privilege_ext_obj\022\037.google.protobuf.Mes"
"sageOptions\030\351\007 \001(\0132!.milvus.proto.common"
".PrivilegeExtBW\n\016io.milvus.grpcB\013CommonP"
"rotoP\001Z3github.com/milvus-io/milvus/inte"
"rnal/proto/commonpb\240\001\001b\006proto3"
;
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_common_2eproto_deps[1] = {
&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
@ -476,7 +477,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_com
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_common_2eproto_once;
static bool descriptor_table_common_2eproto_initialized = false;
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_common_2eproto = {
&descriptor_table_common_2eproto_initialized, descriptor_table_protodef_common_2eproto, "common.proto", 4705,
&descriptor_table_common_2eproto_initialized, descriptor_table_protodef_common_2eproto, "common.proto", 4750,
&descriptor_table_common_2eproto_once, descriptor_table_common_2eproto_sccs, descriptor_table_common_2eproto_deps, 11, 1,
schemas, file_default_instances, TableStruct_common_2eproto::offsets,
file_level_metadata_common_2eproto, 11, file_level_enum_descriptors_common_2eproto, file_level_service_descriptors_common_2eproto,
@ -754,24 +755,25 @@ bool ImportState_IsValid(int value) {
}
}
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ResourceType_descriptor() {
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ObjectType_descriptor() {
::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_common_2eproto);
return file_level_enum_descriptors_common_2eproto[9];
}
bool ResourceType_IsValid(int value) {
bool ObjectType_IsValid(int value) {
switch (value) {
case 0:
case 1:
return true;
default:
return false;
}
}
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ResourcePrivilege_descriptor() {
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ObjectPrivilege_descriptor() {
::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_common_2eproto);
return file_level_enum_descriptors_common_2eproto[10];
}
bool ResourcePrivilege_IsValid(int value) {
bool ObjectPrivilege_IsValid(int value) {
switch (value) {
case 0:
case 1:
@ -3945,16 +3947,16 @@ PrivilegeExt::PrivilegeExt(const PrivilegeExt& from)
: ::PROTOBUF_NAMESPACE_ID::Message(),
_internal_metadata_(nullptr) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
::memcpy(&resource_type_, &from.resource_type_,
static_cast<size_t>(reinterpret_cast<char*>(&resource_name_index_) -
reinterpret_cast<char*>(&resource_type_)) + sizeof(resource_name_index_));
::memcpy(&object_type_, &from.object_type_,
static_cast<size_t>(reinterpret_cast<char*>(&object_name_index_) -
reinterpret_cast<char*>(&object_type_)) + sizeof(object_name_index_));
// @@protoc_insertion_point(copy_constructor:milvus.proto.common.PrivilegeExt)
}
void PrivilegeExt::SharedCtor() {
::memset(&resource_type_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&resource_name_index_) -
reinterpret_cast<char*>(&resource_type_)) + sizeof(resource_name_index_));
::memset(&object_type_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&object_name_index_) -
reinterpret_cast<char*>(&object_type_)) + sizeof(object_name_index_));
}
PrivilegeExt::~PrivilegeExt() {
@ -3980,9 +3982,9 @@ void PrivilegeExt::Clear() {
// Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits;
::memset(&resource_type_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&resource_name_index_) -
reinterpret_cast<char*>(&resource_type_)) + sizeof(resource_name_index_));
::memset(&object_type_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&object_name_index_) -
reinterpret_cast<char*>(&object_type_)) + sizeof(object_name_index_));
_internal_metadata_.Clear();
}
@ -3994,26 +3996,26 @@ const char* PrivilegeExt::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_I
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
CHK_(ptr);
switch (tag >> 3) {
// .milvus.proto.common.ResourceType resource_type = 1;
// .milvus.proto.common.ObjectType object_type = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) {
::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
CHK_(ptr);
set_resource_type(static_cast<::milvus::proto::common::ResourceType>(val));
set_object_type(static_cast<::milvus::proto::common::ObjectType>(val));
} else goto handle_unusual;
continue;
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) {
::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
CHK_(ptr);
set_resource_privilege(static_cast<::milvus::proto::common::ResourcePrivilege>(val));
set_object_privilege(static_cast<::milvus::proto::common::ObjectPrivilege>(val));
} else goto handle_unusual;
continue;
// int32 resource_name_index = 3;
// int32 object_name_index = 3;
case 3:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) {
resource_name_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
object_name_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -4047,41 +4049,41 @@ bool PrivilegeExt::MergePartialFromCodedStream(
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// .milvus.proto.common.ResourceType resource_type = 1;
// .milvus.proto.common.ObjectType object_type = 1;
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (8 & 0xFF)) {
int value = 0;
DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
int, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_ENUM>(
input, &value)));
set_resource_type(static_cast< ::milvus::proto::common::ResourceType >(value));
set_object_type(static_cast< ::milvus::proto::common::ObjectType >(value));
} else {
goto handle_unusual;
}
break;
}
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
case 2: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (16 & 0xFF)) {
int value = 0;
DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
int, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_ENUM>(
input, &value)));
set_resource_privilege(static_cast< ::milvus::proto::common::ResourcePrivilege >(value));
set_object_privilege(static_cast< ::milvus::proto::common::ObjectPrivilege >(value));
} else {
goto handle_unusual;
}
break;
}
// int32 resource_name_index = 3;
// int32 object_name_index = 3;
case 3: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (24 & 0xFF)) {
DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
::PROTOBUF_NAMESPACE_ID::int32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT32>(
input, &resource_name_index_)));
input, &object_name_index_)));
} else {
goto handle_unusual;
}
@ -4115,21 +4117,21 @@ void PrivilegeExt::SerializeWithCachedSizes(
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits;
// .milvus.proto.common.ResourceType resource_type = 1;
if (this->resource_type() != 0) {
// .milvus.proto.common.ObjectType object_type = 1;
if (this->object_type() != 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnum(
1, this->resource_type(), output);
1, this->object_type(), output);
}
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
if (this->resource_privilege() != 0) {
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
if (this->object_privilege() != 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnum(
2, this->resource_privilege(), output);
2, this->object_privilege(), output);
}
// int32 resource_name_index = 3;
if (this->resource_name_index() != 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32(3, this->resource_name_index(), output);
// int32 object_name_index = 3;
if (this->object_name_index() != 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32(3, this->object_name_index(), output);
}
if (_internal_metadata_.have_unknown_fields()) {
@ -4145,21 +4147,21 @@ void PrivilegeExt::SerializeWithCachedSizes(
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits;
// .milvus.proto.common.ResourceType resource_type = 1;
if (this->resource_type() != 0) {
// .milvus.proto.common.ObjectType object_type = 1;
if (this->object_type() != 0) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
1, this->resource_type(), target);
1, this->object_type(), target);
}
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
if (this->resource_privilege() != 0) {
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
if (this->object_privilege() != 0) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
2, this->resource_privilege(), target);
2, this->object_privilege(), target);
}
// int32 resource_name_index = 3;
if (this->resource_name_index() != 0) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->resource_name_index(), target);
// int32 object_name_index = 3;
if (this->object_name_index() != 0) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->object_name_index(), target);
}
if (_internal_metadata_.have_unknown_fields()) {
@ -4183,23 +4185,23 @@ size_t PrivilegeExt::ByteSizeLong() const {
// Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits;
// .milvus.proto.common.ResourceType resource_type = 1;
if (this->resource_type() != 0) {
// .milvus.proto.common.ObjectType object_type = 1;
if (this->object_type() != 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->resource_type());
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->object_type());
}
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
if (this->resource_privilege() != 0) {
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
if (this->object_privilege() != 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->resource_privilege());
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->object_privilege());
}
// int32 resource_name_index = 3;
if (this->resource_name_index() != 0) {
// int32 object_name_index = 3;
if (this->object_name_index() != 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
this->resource_name_index());
this->object_name_index());
}
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
@ -4229,14 +4231,14 @@ void PrivilegeExt::MergeFrom(const PrivilegeExt& from) {
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits;
if (from.resource_type() != 0) {
set_resource_type(from.resource_type());
if (from.object_type() != 0) {
set_object_type(from.object_type());
}
if (from.resource_privilege() != 0) {
set_resource_privilege(from.resource_privilege());
if (from.object_privilege() != 0) {
set_object_privilege(from.object_privilege());
}
if (from.resource_name_index() != 0) {
set_resource_name_index(from.resource_name_index());
if (from.object_name_index() != 0) {
set_object_name_index(from.object_name_index());
}
}
@ -4261,9 +4263,9 @@ bool PrivilegeExt::IsInitialized() const {
void PrivilegeExt::InternalSwap(PrivilegeExt* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(resource_type_, other->resource_type_);
swap(resource_privilege_, other->resource_privilege_);
swap(resource_name_index_, other->resource_name_index_);
swap(object_type_, other->object_type_);
swap(object_privilege_, other->object_privilege_);
swap(object_name_index_, other->object_name_index_);
}
::PROTOBUF_NAMESPACE_ID::Metadata PrivilegeExt::GetMetadata() const {

View File

@ -478,62 +478,63 @@ inline bool ImportState_Parse(
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ImportState>(
ImportState_descriptor(), name, value);
}
enum ResourceType : int {
enum ObjectType : int {
Collection = 0,
ResourceType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
ResourceType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
Global = 1,
ObjectType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
ObjectType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
};
bool ResourceType_IsValid(int value);
constexpr ResourceType ResourceType_MIN = Collection;
constexpr ResourceType ResourceType_MAX = Collection;
constexpr int ResourceType_ARRAYSIZE = ResourceType_MAX + 1;
bool ObjectType_IsValid(int value);
constexpr ObjectType ObjectType_MIN = Collection;
constexpr ObjectType ObjectType_MAX = Global;
constexpr int ObjectType_ARRAYSIZE = ObjectType_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ResourceType_descriptor();
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ObjectType_descriptor();
template<typename T>
inline const std::string& ResourceType_Name(T enum_t_value) {
static_assert(::std::is_same<T, ResourceType>::value ||
inline const std::string& ObjectType_Name(T enum_t_value) {
static_assert(::std::is_same<T, ObjectType>::value ||
::std::is_integral<T>::value,
"Incorrect type passed to function ResourceType_Name.");
"Incorrect type passed to function ObjectType_Name.");
return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
ResourceType_descriptor(), enum_t_value);
ObjectType_descriptor(), enum_t_value);
}
inline bool ResourceType_Parse(
const std::string& name, ResourceType* value) {
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ResourceType>(
ResourceType_descriptor(), name, value);
inline bool ObjectType_Parse(
const std::string& name, ObjectType* value) {
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ObjectType>(
ObjectType_descriptor(), name, value);
}
enum ResourcePrivilege : int {
enum ObjectPrivilege : int {
PrivilegeAll = 0,
PrivilegeCreate = 1,
PrivilegeDrop = 2,
PrivilegeAlter = 3,
PrivilegeRead = 4,
PrivilegeCreateCollection = 1,
PrivilegeDropCollection = 2,
PrivilegeDescribeCollection = 3,
PrivilegeShowCollections = 4,
PrivilegeLoad = 5,
PrivilegeRelease = 6,
PrivilegeCompact = 7,
PrivilegeCompaction = 7,
PrivilegeInsert = 8,
PrivilegeDelete = 9,
ResourcePrivilege_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
ResourcePrivilege_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
ObjectPrivilege_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
ObjectPrivilege_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
};
bool ResourcePrivilege_IsValid(int value);
constexpr ResourcePrivilege ResourcePrivilege_MIN = PrivilegeAll;
constexpr ResourcePrivilege ResourcePrivilege_MAX = PrivilegeDelete;
constexpr int ResourcePrivilege_ARRAYSIZE = ResourcePrivilege_MAX + 1;
bool ObjectPrivilege_IsValid(int value);
constexpr ObjectPrivilege ObjectPrivilege_MIN = PrivilegeAll;
constexpr ObjectPrivilege ObjectPrivilege_MAX = PrivilegeDelete;
constexpr int ObjectPrivilege_ARRAYSIZE = ObjectPrivilege_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ResourcePrivilege_descriptor();
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ObjectPrivilege_descriptor();
template<typename T>
inline const std::string& ResourcePrivilege_Name(T enum_t_value) {
static_assert(::std::is_same<T, ResourcePrivilege>::value ||
inline const std::string& ObjectPrivilege_Name(T enum_t_value) {
static_assert(::std::is_same<T, ObjectPrivilege>::value ||
::std::is_integral<T>::value,
"Incorrect type passed to function ResourcePrivilege_Name.");
"Incorrect type passed to function ObjectPrivilege_Name.");
return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
ResourcePrivilege_descriptor(), enum_t_value);
ObjectPrivilege_descriptor(), enum_t_value);
}
inline bool ResourcePrivilege_Parse(
const std::string& name, ResourcePrivilege* value) {
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ResourcePrivilege>(
ResourcePrivilege_descriptor(), name, value);
inline bool ObjectPrivilege_Parse(
const std::string& name, ObjectPrivilege* value) {
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ObjectPrivilege>(
ObjectPrivilege_descriptor(), name, value);
}
// ===================================================================
@ -2108,33 +2109,33 @@ class PrivilegeExt :
// accessors -------------------------------------------------------
enum : int {
kResourceTypeFieldNumber = 1,
kResourcePrivilegeFieldNumber = 2,
kResourceNameIndexFieldNumber = 3,
kObjectTypeFieldNumber = 1,
kObjectPrivilegeFieldNumber = 2,
kObjectNameIndexFieldNumber = 3,
};
// .milvus.proto.common.ResourceType resource_type = 1;
void clear_resource_type();
::milvus::proto::common::ResourceType resource_type() const;
void set_resource_type(::milvus::proto::common::ResourceType value);
// .milvus.proto.common.ObjectType object_type = 1;
void clear_object_type();
::milvus::proto::common::ObjectType object_type() const;
void set_object_type(::milvus::proto::common::ObjectType value);
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
void clear_resource_privilege();
::milvus::proto::common::ResourcePrivilege resource_privilege() const;
void set_resource_privilege(::milvus::proto::common::ResourcePrivilege value);
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
void clear_object_privilege();
::milvus::proto::common::ObjectPrivilege object_privilege() const;
void set_object_privilege(::milvus::proto::common::ObjectPrivilege value);
// int32 resource_name_index = 3;
void clear_resource_name_index();
::PROTOBUF_NAMESPACE_ID::int32 resource_name_index() const;
void set_resource_name_index(::PROTOBUF_NAMESPACE_ID::int32 value);
// int32 object_name_index = 3;
void clear_object_name_index();
::PROTOBUF_NAMESPACE_ID::int32 object_name_index() const;
void set_object_name_index(::PROTOBUF_NAMESPACE_ID::int32 value);
// @@protoc_insertion_point(class_scope:milvus.proto.common.PrivilegeExt)
private:
class _Internal;
::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_;
int resource_type_;
int resource_privilege_;
::PROTOBUF_NAMESPACE_ID::int32 resource_name_index_;
int object_type_;
int object_privilege_;
::PROTOBUF_NAMESPACE_ID::int32 object_name_index_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_common_2eproto;
};
@ -2947,46 +2948,46 @@ inline void DMLMsgHeader::set_allocated_shardname(std::string* shardname) {
// PrivilegeExt
// .milvus.proto.common.ResourceType resource_type = 1;
inline void PrivilegeExt::clear_resource_type() {
resource_type_ = 0;
// .milvus.proto.common.ObjectType object_type = 1;
inline void PrivilegeExt::clear_object_type() {
object_type_ = 0;
}
inline ::milvus::proto::common::ResourceType PrivilegeExt::resource_type() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.resource_type)
return static_cast< ::milvus::proto::common::ResourceType >(resource_type_);
inline ::milvus::proto::common::ObjectType PrivilegeExt::object_type() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.object_type)
return static_cast< ::milvus::proto::common::ObjectType >(object_type_);
}
inline void PrivilegeExt::set_resource_type(::milvus::proto::common::ResourceType value) {
inline void PrivilegeExt::set_object_type(::milvus::proto::common::ObjectType value) {
resource_type_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.resource_type)
object_type_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.object_type)
}
// .milvus.proto.common.ResourcePrivilege resource_privilege = 2;
inline void PrivilegeExt::clear_resource_privilege() {
resource_privilege_ = 0;
// .milvus.proto.common.ObjectPrivilege object_privilege = 2;
inline void PrivilegeExt::clear_object_privilege() {
object_privilege_ = 0;
}
inline ::milvus::proto::common::ResourcePrivilege PrivilegeExt::resource_privilege() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.resource_privilege)
return static_cast< ::milvus::proto::common::ResourcePrivilege >(resource_privilege_);
inline ::milvus::proto::common::ObjectPrivilege PrivilegeExt::object_privilege() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.object_privilege)
return static_cast< ::milvus::proto::common::ObjectPrivilege >(object_privilege_);
}
inline void PrivilegeExt::set_resource_privilege(::milvus::proto::common::ResourcePrivilege value) {
inline void PrivilegeExt::set_object_privilege(::milvus::proto::common::ObjectPrivilege value) {
resource_privilege_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.resource_privilege)
object_privilege_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.object_privilege)
}
// int32 resource_name_index = 3;
inline void PrivilegeExt::clear_resource_name_index() {
resource_name_index_ = 0;
// int32 object_name_index = 3;
inline void PrivilegeExt::clear_object_name_index() {
object_name_index_ = 0;
}
inline ::PROTOBUF_NAMESPACE_ID::int32 PrivilegeExt::resource_name_index() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.resource_name_index)
return resource_name_index_;
inline ::PROTOBUF_NAMESPACE_ID::int32 PrivilegeExt::object_name_index() const {
// @@protoc_insertion_point(field_get:milvus.proto.common.PrivilegeExt.object_name_index)
return object_name_index_;
}
inline void PrivilegeExt::set_resource_name_index(::PROTOBUF_NAMESPACE_ID::int32 value) {
inline void PrivilegeExt::set_object_name_index(::PROTOBUF_NAMESPACE_ID::int32 value) {
resource_name_index_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.resource_name_index)
object_name_index_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.common.PrivilegeExt.object_name_index)
}
#ifdef __GNUC__
@ -3066,15 +3067,15 @@ template <>
inline const EnumDescriptor* GetEnumDescriptor< ::milvus::proto::common::ImportState>() {
return ::milvus::proto::common::ImportState_descriptor();
}
template <> struct is_proto_enum< ::milvus::proto::common::ResourceType> : ::std::true_type {};
template <> struct is_proto_enum< ::milvus::proto::common::ObjectType> : ::std::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::milvus::proto::common::ResourceType>() {
return ::milvus::proto::common::ResourceType_descriptor();
inline const EnumDescriptor* GetEnumDescriptor< ::milvus::proto::common::ObjectType>() {
return ::milvus::proto::common::ObjectType_descriptor();
}
template <> struct is_proto_enum< ::milvus::proto::common::ResourcePrivilege> : ::std::true_type {};
template <> struct is_proto_enum< ::milvus::proto::common::ObjectPrivilege> : ::std::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::milvus::proto::common::ResourcePrivilege>() {
return ::milvus::proto::common::ResourcePrivilege_descriptor();
inline const EnumDescriptor* GetEnumDescriptor< ::milvus::proto::common::ObjectPrivilege>() {
return ::milvus::proto::common::ObjectPrivilege_descriptor();
}
PROTOBUF_NAMESPACE_CLOSE

View File

@ -662,6 +662,38 @@ func (m *mockRootCoordService) GetCredential(ctx context.Context, req *rootcoord
panic("implement me")
}
func (m *mockRootCoordService) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
panic("implement me")
}
func (m *mockRootCoordService) DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
panic("implement me")
}
func (m *mockRootCoordService) OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
panic("implement me")
}
func (m *mockRootCoordService) SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
panic("implement me")
}
func (m *mockRootCoordService) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
panic("implement me")
}
func (m *mockRootCoordService) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
panic("implement me")
}
func (m *mockRootCoordService) SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
panic("implement me")
}
func (m *mockRootCoordService) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}}, nil
}
type mockHandler struct {
}

View File

@ -81,6 +81,11 @@ func Test_NewClient(t *testing.T) {
r8, err := client.UpdateCredentialCache(ctx, nil)
retCheck(retNotNil, r8, err)
{
r, err := client.RefreshPolicyInfoCache(ctx, nil)
retCheck(retNotNil, r, err)
}
}
client.grpcClient = &mock.GRPCClientBase{
@ -150,6 +155,11 @@ func Test_NewClient(t *testing.T) {
r8Timeout, err := client.UpdateCredentialCache(shortCtx, nil)
retCheck(r8Timeout, err)
{
rTimeout, err := client.RefreshPolicyInfoCache(shortCtx, nil)
retCheck(rTimeout, err)
}
// cleanup
err = client.Stop()
assert.Nil(t, err)

View File

@ -170,6 +170,7 @@ func (s *Server) startExternalGrpc(grpcPort int, errChan chan error) {
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
ot.UnaryServerInterceptor(opts...),
grpc_auth.UnaryServerInterceptor(proxy.AuthenticationInterceptor),
proxy.UnaryServerInterceptor(proxy.PrivilegeInterceptor),
)),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
ot.StreamServerInterceptor(opts...),
@ -833,47 +834,34 @@ func (s *Server) ListCredUsers(ctx context.Context, req *milvuspb.ListCredUsersR
return s.proxy.ListCredUsers(ctx, req)
}
func (s *Server) CreateRole(ctx context.Context, request *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
return s.proxy.CreateRole(ctx, req)
}
func (s *Server) DropRole(ctx context.Context, request *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
return s.proxy.DropRole(ctx, req)
}
func (s *Server) OperateUserRole(ctx context.Context, request *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
return s.proxy.OperateUserRole(ctx, req)
}
func (s *Server) SelectRole(ctx context.Context, request *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
//TODO implement me
panic("implement me")
func (s *Server) SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
return s.proxy.SelectRole(ctx, req)
}
func (s *Server) SelectUser(ctx context.Context, request *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
//TODO implement me
panic("implement me")
func (s *Server) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
return s.proxy.SelectUser(ctx, req)
}
func (s *Server) SelectResource(ctx context.Context, request *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error) {
//TODO implement me
panic("implement me")
func (s *Server) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return s.proxy.OperatePrivilege(ctx, req)
}
func (s *Server) OperatePrivilege(ctx context.Context, request *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
return s.proxy.SelectGrant(ctx, req)
}
func (s *Server) SelectGrant(ctx context.Context, request *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
//TODO implement me
panic("implement me")
}
func (s *Server) RefreshPolicyInfoCache(ctx context.Context, request *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
return s.proxy.RefreshPolicyInfoCache(ctx, req)
}

View File

@ -258,6 +258,38 @@ func (m *MockRootCoord) GetCredential(ctx context.Context, req *rootcoordpb.GetC
return nil, nil
}
func (m *MockRootCoord) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockRootCoord) DropRole(ctx context.Context, in *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockRootCoord) OperateUserRole(ctx context.Context, in *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockRootCoord) SelectRole(ctx context.Context, in *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
return nil, nil
}
func (m *MockRootCoord) SelectUser(ctx context.Context, in *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
return nil, nil
}
func (m *MockRootCoord) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockRootCoord) SelectGrant(ctx context.Context, in *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
return nil, nil
}
func (m *MockRootCoord) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return nil, nil
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type MockIndexCoord struct {
MockBase
@ -804,6 +836,38 @@ func (m *MockProxy) ListCredUsers(ctx context.Context, req *milvuspb.ListCredUse
return nil, nil
}
func (m *MockProxy) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockProxy) DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockProxy) OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockProxy) SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
return nil, nil
}
func (m *MockProxy) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
return nil, nil
}
func (m *MockProxy) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return nil, nil
}
func (m *MockProxy) SelectGrant(ctx context.Context, in *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
return nil, nil
}
func (m *MockProxy) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
return nil, nil
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type WaitOption struct {
@ -1184,6 +1248,46 @@ func Test_NewServer(t *testing.T) {
assert.Nil(t, err)
})
t.Run("CreateRole", func(t *testing.T) {
_, err := server.CreateRole(ctx, nil)
assert.Nil(t, err)
})
t.Run("DropRole", func(t *testing.T) {
_, err := server.DropRole(ctx, nil)
assert.Nil(t, err)
})
t.Run("OperateUserRole", func(t *testing.T) {
_, err := server.OperateUserRole(ctx, nil)
assert.Nil(t, err)
})
t.Run("SelectRole", func(t *testing.T) {
_, err := server.SelectRole(ctx, nil)
assert.Nil(t, err)
})
t.Run("SelectUser", func(t *testing.T) {
_, err := server.SelectUser(ctx, nil)
assert.Nil(t, err)
})
t.Run("OperatePrivilege", func(t *testing.T) {
_, err := server.OperatePrivilege(ctx, nil)
assert.Nil(t, err)
})
t.Run("SelectGrant", func(t *testing.T) {
_, err := server.SelectGrant(ctx, nil)
assert.Nil(t, err)
})
t.Run("RefreshPrivilegeInfoCache", func(t *testing.T) {
_, err := server.RefreshPolicyInfoCache(ctx, nil)
assert.Nil(t, err)
})
err = server.Stop()
assert.Nil(t, err)

View File

@ -712,19 +712,6 @@ func (c *Client) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest
return ret.(*milvuspb.SelectUserResponse), err
}
func (c *Client) SelectResource(ctx context.Context, req *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error) {
ret, err := c.grpcClient.ReCall(ctx, func(client interface{}) (interface{}, error) {
if !funcutil.CheckCtxValid(ctx) {
return nil, ctx.Err()
}
return client.(rootcoordpb.RootCoordClient).SelectResource(ctx, req)
})
if err != nil {
return nil, err
}
return ret.(*milvuspb.SelectResourceResponse), err
}
func (c *Client) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
ret, err := c.grpcClient.ReCall(ctx, func(client interface{}) (interface{}, error) {
if !funcutil.CheckCtxValid(ctx) {

View File

@ -60,110 +60,178 @@ func Test_NewClient(t *testing.T) {
}
}
r1, err := client.GetComponentStates(ctx)
retCheck(retNotNil, r1, err)
r2, err := client.GetTimeTickChannel(ctx)
retCheck(retNotNil, r2, err)
r3, err := client.GetStatisticsChannel(ctx)
retCheck(retNotNil, r3, err)
r4, err := client.CreateCollection(ctx, nil)
retCheck(retNotNil, r4, err)
r5, err := client.DropCollection(ctx, nil)
retCheck(retNotNil, r5, err)
r6, err := client.HasCollection(ctx, nil)
retCheck(retNotNil, r6, err)
r7, err := client.DescribeCollection(ctx, nil)
retCheck(retNotNil, r7, err)
r8, err := client.ShowCollections(ctx, nil)
retCheck(retNotNil, r8, err)
r9, err := client.CreatePartition(ctx, nil)
retCheck(retNotNil, r9, err)
r10, err := client.DropPartition(ctx, nil)
retCheck(retNotNil, r10, err)
r11, err := client.HasPartition(ctx, nil)
retCheck(retNotNil, r11, err)
r12, err := client.ShowPartitions(ctx, nil)
retCheck(retNotNil, r12, err)
r13, err := client.CreateIndex(ctx, nil)
retCheck(retNotNil, r13, err)
r14, err := client.DropIndex(ctx, nil)
retCheck(retNotNil, r14, err)
r15, err := client.DescribeIndex(ctx, nil)
retCheck(retNotNil, r15, err)
r16, err := client.AllocTimestamp(ctx, nil)
retCheck(retNotNil, r16, err)
r17, err := client.AllocID(ctx, nil)
retCheck(retNotNil, r17, err)
r18, err := client.UpdateChannelTimeTick(ctx, nil)
retCheck(retNotNil, r18, err)
r19, err := client.DescribeSegment(ctx, nil)
retCheck(retNotNil, r19, err)
r20, err := client.ShowSegments(ctx, nil)
retCheck(retNotNil, r20, err)
r21, err := client.ReleaseDQLMessageStream(ctx, nil)
retCheck(retNotNil, r21, err)
r22, err := client.SegmentFlushCompleted(ctx, nil)
retCheck(retNotNil, r22, err)
r23, err := client.GetMetrics(ctx, nil)
retCheck(retNotNil, r23, err)
r24, err := client.CreateAlias(ctx, nil)
retCheck(retNotNil, r24, err)
r25, err := client.DropAlias(ctx, nil)
retCheck(retNotNil, r25, err)
r26, err := client.AlterAlias(ctx, nil)
retCheck(retNotNil, r26, err)
r27, err := client.Import(ctx, nil)
retCheck(retNotNil, r27, err)
r28, err := client.GetImportState(ctx, nil)
retCheck(retNotNil, r28, err)
r29, err := client.ReportImport(ctx, nil)
retCheck(retNotNil, r29, err)
r30, err := client.CreateCredential(ctx, nil)
retCheck(retNotNil, r30, err)
r31, err := client.GetCredential(ctx, nil)
retCheck(retNotNil, r31, err)
r32, err := client.UpdateCredential(ctx, nil)
retCheck(retNotNil, r32, err)
r33, err := client.DeleteCredential(ctx, nil)
retCheck(retNotNil, r33, err)
r34, err := client.ListCredUsers(ctx, nil)
retCheck(retNotNil, r34, err)
r35, err := client.InvalidateCollectionMetaCache(ctx, nil)
retCheck(retNotNil, r35, err)
{
r, err := client.GetComponentStates(ctx)
retCheck(retNotNil, r, err)
}
{
r, err := client.GetTimeTickChannel(ctx)
retCheck(retNotNil, r, err)
}
{
r, err := client.GetStatisticsChannel(ctx)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreateCollection(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DropCollection(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.HasCollection(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DescribeCollection(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ShowCollections(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreatePartition(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DropPartition(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.HasPartition(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ShowPartitions(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreateIndex(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DropIndex(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DescribeIndex(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.AllocTimestamp(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.AllocID(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.UpdateChannelTimeTick(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DescribeSegment(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ShowSegments(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ReleaseDQLMessageStream(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.SegmentFlushCompleted(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.GetMetrics(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreateAlias(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DropAlias(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.AlterAlias(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.Import(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.GetImportState(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ReportImport(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreateCredential(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.GetCredential(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.UpdateCredential(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DeleteCredential(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ListCredUsers(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.InvalidateCollectionMetaCache(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.CreateRole(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.DropRole(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.OperateUserRole(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.SelectRole(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.SelectUser(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.OperatePrivilege(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.SelectGrant(ctx, nil)
retCheck(retNotNil, r, err)
}
{
r, err := client.ListPolicy(ctx, nil)
retCheck(retNotNil, r, err)
}
}
client.grpcClient = &mock.GRPCClientBase{
@ -210,114 +278,182 @@ func Test_NewClient(t *testing.T) {
assert.Nil(t, ret)
assert.NotNil(t, err)
}
r1Timeout, err := client.GetComponentStates(shortCtx)
retCheck(r1Timeout, err)
r2Timeout, err := client.GetTimeTickChannel(shortCtx)
retCheck(r2Timeout, err)
r3Timeout, err := client.GetStatisticsChannel(shortCtx)
retCheck(r3Timeout, err)
r4Timeout, err := client.CreateCollection(shortCtx, nil)
retCheck(r4Timeout, err)
r5Timeout, err := client.DropCollection(shortCtx, nil)
retCheck(r5Timeout, err)
r6Timeout, err := client.HasCollection(shortCtx, nil)
retCheck(r6Timeout, err)
r7Timeout, err := client.DescribeCollection(shortCtx, nil)
retCheck(r7Timeout, err)
r8Timeout, err := client.ShowCollections(shortCtx, nil)
retCheck(r8Timeout, err)
r9Timeout, err := client.CreatePartition(shortCtx, nil)
retCheck(r9Timeout, err)
r10Timeout, err := client.DropPartition(shortCtx, nil)
retCheck(r10Timeout, err)
r11Timeout, err := client.HasPartition(shortCtx, nil)
retCheck(r11Timeout, err)
r12Timeout, err := client.ShowPartitions(shortCtx, nil)
retCheck(r12Timeout, err)
r13Timeout, err := client.CreateIndex(shortCtx, nil)
retCheck(r13Timeout, err)
r14Timeout, err := client.DropIndex(shortCtx, nil)
retCheck(r14Timeout, err)
r15Timeout, err := client.DescribeIndex(shortCtx, nil)
retCheck(r15Timeout, err)
r16Timeout, err := client.AllocTimestamp(shortCtx, nil)
retCheck(r16Timeout, err)
r17Timeout, err := client.AllocID(shortCtx, nil)
retCheck(r17Timeout, err)
r18Timeout, err := client.UpdateChannelTimeTick(shortCtx, nil)
retCheck(r18Timeout, err)
r19Timeout, err := client.DescribeSegment(shortCtx, nil)
retCheck(r19Timeout, err)
r20Timeout, err := client.ShowSegments(shortCtx, nil)
retCheck(r20Timeout, err)
r21Timeout, err := client.ReleaseDQLMessageStream(shortCtx, nil)
retCheck(r21Timeout, err)
r22Timeout, err := client.SegmentFlushCompleted(shortCtx, nil)
retCheck(r22Timeout, err)
r23Timeout, err := client.GetMetrics(shortCtx, nil)
retCheck(r23Timeout, err)
r24Timeout, err := client.CreateAlias(shortCtx, nil)
retCheck(r24Timeout, err)
r25Timeout, err := client.DropAlias(shortCtx, nil)
retCheck(r25Timeout, err)
r26Timeout, err := client.AlterAlias(shortCtx, nil)
retCheck(r26Timeout, err)
r27Timeout, err := client.Import(shortCtx, nil)
retCheck(r27Timeout, err)
r28Timeout, err := client.GetImportState(shortCtx, nil)
retCheck(r28Timeout, err)
r29Timeout, err := client.ReportImport(shortCtx, nil)
retCheck(r29Timeout, err)
r30Timeout, err := client.CreateCredential(shortCtx, nil)
retCheck(r30Timeout, err)
r31Timeout, err := client.GetCredential(shortCtx, nil)
retCheck(r31Timeout, err)
r32Timeout, err := client.UpdateCredential(shortCtx, nil)
retCheck(r32Timeout, err)
r33Timeout, err := client.DeleteCredential(shortCtx, nil)
retCheck(r33Timeout, err)
r34Timeout, err := client.ListCredUsers(shortCtx, nil)
retCheck(r34Timeout, err)
r35Timeout, err := client.ListImportTasks(shortCtx, nil)
retCheck(r35Timeout, err)
r36Timeout, err := client.InvalidateCollectionMetaCache(shortCtx, nil)
retCheck(r36Timeout, err)
{
rTimeout, err := client.GetComponentStates(shortCtx)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.GetTimeTickChannel(shortCtx)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.GetStatisticsChannel(shortCtx)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreateCollection(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DropCollection(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.HasCollection(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DescribeCollection(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ShowCollections(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreatePartition(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DropPartition(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.HasPartition(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ShowPartitions(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreateIndex(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DropIndex(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DescribeIndex(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.AllocTimestamp(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.AllocID(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.UpdateChannelTimeTick(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DescribeSegment(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ShowSegments(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ReleaseDQLMessageStream(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.SegmentFlushCompleted(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.GetMetrics(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreateAlias(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DropAlias(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.AlterAlias(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.Import(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.GetImportState(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ReportImport(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreateCredential(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.GetCredential(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.UpdateCredential(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DeleteCredential(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ListCredUsers(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ListImportTasks(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.InvalidateCollectionMetaCache(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.CreateRole(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.DropRole(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.OperateUserRole(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.SelectRole(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.SelectUser(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.OperatePrivilege(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.SelectGrant(shortCtx, nil)
retCheck(rTimeout, err)
}
{
rTimeout, err := client.ListPolicy(shortCtx, nil)
retCheck(rTimeout, err)
}
// clean up
err = client.Stop()

View File

@ -491,46 +491,33 @@ func (s *Server) ListCredUsers(ctx context.Context, request *milvuspb.ListCredUs
}
func (s *Server) CreateRole(ctx context.Context, request *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.CreateRole(ctx, request)
}
func (s *Server) DropRole(ctx context.Context, request *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.DropRole(ctx, request)
}
func (s *Server) OperateUserRole(ctx context.Context, request *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.OperateUserRole(ctx, request)
}
func (s *Server) SelectRole(ctx context.Context, request *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.SelectRole(ctx, request)
}
func (s *Server) SelectUser(ctx context.Context, request *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.SelectUser(ctx, request)
}
func (s *Server) SelectResource(ctx context.Context, request *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error) {
//TODO implement me
panic("implement me")
}
func (s *Server) OperatePrivilege(ctx context.Context, info *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (s *Server) OperatePrivilege(ctx context.Context, request *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return s.rootCoord.OperatePrivilege(ctx, request)
}
func (s *Server) SelectGrant(ctx context.Context, request *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.SelectGrant(ctx, request)
}
func (s *Server) ListPolicy(ctx context.Context, request *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
//TODO implement me
panic("implement me")
return s.rootCoord.ListPolicy(ctx, request)
}

View File

@ -118,7 +118,7 @@ func TestLevelGetterAndSetter(t *testing.T) {
}
func TestUpdateLogLevelThroughHttp(t *testing.T) {
httpServer := &http.Server{Addr: ":9081"}
httpServer := &http.Server{Addr: ":9081", ReadHeaderTimeout: time.Second * 3}
go func() {
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
Fatal(err.Error())

View File

@ -3,6 +3,8 @@ package metastore
import (
"context"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus/internal/util/typeutil"
)
@ -34,6 +36,16 @@ type Catalog interface {
DropCredential(ctx context.Context, username string) error
ListCredentials(ctx context.Context) ([]string, error)
CreateRole(ctx context.Context, tenant string, entity *milvuspb.RoleEntity) error
DropRole(ctx context.Context, tenant string, roleName string) error
OperateUserRole(ctx context.Context, tenant string, userEntity *milvuspb.UserEntity, roleEntity *milvuspb.RoleEntity, operateType milvuspb.OperateUserRoleType) error
SelectRole(ctx context.Context, tenant string, entity *milvuspb.RoleEntity, includeUserInfo bool) ([]*milvuspb.RoleResult, error)
SelectUser(ctx context.Context, tenant string, entity *milvuspb.UserEntity, includeRoleInfo bool) ([]*milvuspb.UserResult, error)
OperatePrivilege(ctx context.Context, tenant string, entity *milvuspb.GrantEntity, operateType milvuspb.OperatePrivilegeType) error
SelectGrant(ctx context.Context, tenant string, entity *milvuspb.GrantEntity) ([]*milvuspb.GrantEntity, error)
ListPolicy(ctx context.Context, tenant string) ([]string, error)
ListUserRole(ctx context.Context, tenant string) ([]string, error)
Close()
}

View File

@ -10,6 +10,11 @@ import (
"reflect"
"strconv"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/metastore"
"github.com/golang/protobuf/proto"
@ -578,6 +583,367 @@ func (kc *Catalog) ListCredentials(ctx context.Context) ([]string, error) {
return usernames, nil
}
func (kc *Catalog) CreateRole(ctx context.Context, tenant string, entity *milvuspb.RoleEntity) error {
k := funcutil.HandleTenantForEtcdKey(RolePrefix, tenant, entity.Name)
err := kc.Txn.Save(k, "")
if err != nil {
log.Error("fail to create role", zap.String("key", k), zap.Error(err))
return err
}
return nil
}
func (kc *Catalog) DropRole(ctx context.Context, tenant string, roleName string) error {
k := funcutil.HandleTenantForEtcdKey(RolePrefix, tenant, roleName)
err := kc.Txn.Remove(k)
if err != nil {
log.Error("fail to drop role", zap.String("key", k), zap.Error(err))
return err
}
return nil
}
func (kc *Catalog) OperateUserRole(ctx context.Context, tenant string, userEntity *milvuspb.UserEntity, roleEntity *milvuspb.RoleEntity, operateType milvuspb.OperateUserRoleType) error {
k := funcutil.HandleTenantForEtcdKey(RoleMappingPrefix, tenant, fmt.Sprintf("%s/%s", userEntity.Name, roleEntity.Name))
var err error
if operateType == milvuspb.OperateUserRoleType_AddUserToRole {
err = kc.Txn.Save(k, "")
if err != nil {
log.Error("fail to add user to role", zap.String("key", k), zap.Error(err))
}
} else if operateType == milvuspb.OperateUserRoleType_RemoveUserFromRole {
err = kc.Txn.Remove(k)
if err != nil {
log.Error("fail to remove user from role", zap.String("key", k), zap.Error(err))
}
} else {
err = fmt.Errorf("invalid operate user role type, operate type: %d", operateType)
}
return err
}
func (kc *Catalog) SelectRole(ctx context.Context, tenant string, entity *milvuspb.RoleEntity, includeUserInfo bool) ([]*milvuspb.RoleResult, error) {
var results []*milvuspb.RoleResult
roleToUsers := make(map[string][]string)
if includeUserInfo {
roleMappingKey := funcutil.HandleTenantForEtcdKey(RoleMappingPrefix, tenant, "")
keys, _, err := kc.Txn.LoadWithPrefix(roleMappingKey)
if err != nil {
log.Error("fail to load role mappings", zap.String("key", roleMappingKey), zap.Error(err))
return results, err
}
for _, key := range keys {
roleMappingInfos := typeutil.AfterN(key, roleMappingKey+"/", "/")
if len(roleMappingInfos) != 2 {
log.Warn("invalid role mapping key", zap.String("key", key))
continue
}
username := roleMappingInfos[0]
roleName := roleMappingInfos[1]
roleToUsers[roleName] = append(roleToUsers[roleName], username)
}
}
appendRoleResult := func(roleName string) {
var users []*milvuspb.UserEntity
for _, username := range roleToUsers[roleName] {
users = append(users, &milvuspb.UserEntity{Name: username})
}
results = append(results, &milvuspb.RoleResult{
Role: &milvuspb.RoleEntity{Name: roleName},
Users: users,
})
}
if entity == nil {
roleKey := funcutil.HandleTenantForEtcdKey(RolePrefix, tenant, "")
keys, _, err := kc.Txn.LoadWithPrefix(roleKey)
if err != nil {
log.Error("fail to load roles", zap.String("key", roleKey), zap.Error(err))
return results, err
}
for _, key := range keys {
infoArr := typeutil.AfterN(key, roleKey+"/", "/")
if len(infoArr) != 1 || len(infoArr[0]) == 0 {
log.Warn("invalid role key", zap.String("key", key))
continue
}
appendRoleResult(infoArr[0])
}
} else {
if funcutil.IsEmptyString(entity.Name) {
return results, fmt.Errorf("role name in the role entity is empty")
}
roleKey := funcutil.HandleTenantForEtcdKey(RolePrefix, tenant, entity.Name)
_, err := kc.Txn.Load(roleKey)
if err != nil {
log.Error("fail to load a role", zap.String("key", roleKey), zap.Error(err))
return results, err
}
appendRoleResult(entity.Name)
}
return results, nil
}
func (kc *Catalog) getRolesByUsername(tenant string, username string) ([]string, error) {
var roles []string
k := funcutil.HandleTenantForEtcdKey(RoleMappingPrefix, tenant, username)
keys, _, err := kc.Txn.LoadWithPrefix(k)
if err != nil {
log.Error("fail to load role mappings by the username", zap.String("key", k), zap.Error(err))
return roles, err
}
for _, key := range keys {
roleMappingInfos := typeutil.AfterN(key, k+"/", "/")
if len(roleMappingInfos) != 1 {
log.Warn("invalid role mapping key", zap.String("key", key))
continue
}
roles = append(roles, roleMappingInfos[0])
}
return roles, nil
}
// getUserResult get the user result by the username. And never return the error because the error means the user isn't added to a role.
func (kc *Catalog) getUserResult(tenant string, username string, includeRoleInfo bool) (*milvuspb.UserResult, error) {
result := &milvuspb.UserResult{User: &milvuspb.UserEntity{Name: username}}
if !includeRoleInfo {
return result, nil
}
roleNames, err := kc.getRolesByUsername(tenant, username)
if err != nil {
log.Warn("fail to get roles by the username", zap.Error(err))
return result, err
}
var roles []*milvuspb.RoleEntity
for _, roleName := range roleNames {
roles = append(roles, &milvuspb.RoleEntity{Name: roleName})
}
result.Roles = roles
return result, nil
}
func (kc *Catalog) SelectUser(ctx context.Context, tenant string, entity *milvuspb.UserEntity, includeRoleInfo bool) ([]*milvuspb.UserResult, error) {
var (
usernames []string
err error
results []*milvuspb.UserResult
)
appendUserResult := func(username string) error {
result, err := kc.getUserResult(tenant, username, includeRoleInfo)
if err != nil {
return err
}
results = append(results, result)
return nil
}
if entity == nil {
usernames, err = kc.ListCredentials(ctx)
if err != nil {
return results, err
}
} else {
if funcutil.IsEmptyString(entity.Name) {
return results, fmt.Errorf("username in the user entity is empty")
}
_, err = kc.GetCredential(ctx, entity.Name)
if err != nil {
return results, err
}
usernames = append(usernames, entity.Name)
}
for _, username := range usernames {
err = appendUserResult(username)
if err != nil {
return nil, err
}
}
return results, nil
}
func (kc *Catalog) OperatePrivilege(ctx context.Context, tenant string, entity *milvuspb.GrantEntity, operateType milvuspb.OperatePrivilegeType) error {
privilegeName := entity.Grantor.Privilege.Name
k := funcutil.HandleTenantForEtcdKey(GranteePrefix, tenant, fmt.Sprintf("%s/%s/%s", entity.Role.Name, entity.Object.Name, entity.ObjectName))
curGrantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{}
v, err := kc.Txn.Load(k)
if err != nil {
log.Warn("fail to load grant privilege entity", zap.String("key", k), zap.Any("type", operateType), zap.Error(err))
if funcutil.IsRevoke(operateType) {
return err
}
if !funcutil.IsKeyNotExistError(err) {
return err
}
curGrantPrivilegeEntity.Entities = append(curGrantPrivilegeEntity.Entities, &milvuspb.GrantorEntity{
Privilege: &milvuspb.PrivilegeEntity{Name: privilegeName},
User: &milvuspb.UserEntity{Name: entity.Grantor.User.Name},
})
} else {
err = proto.Unmarshal([]byte(v), curGrantPrivilegeEntity)
if err != nil {
log.Error("fail to unmarshal the grant privilege entity", zap.String("key", k), zap.Any("type", operateType), zap.Error(err))
return err
}
isExisted := false
dropIndex := -1
for entityIndex, grantorEntity := range curGrantPrivilegeEntity.Entities {
if grantorEntity.Privilege.Name == privilegeName {
isExisted = true
dropIndex = entityIndex
break
}
}
if !isExisted && funcutil.IsGrant(operateType) {
curGrantPrivilegeEntity.Entities = append(curGrantPrivilegeEntity.Entities, &milvuspb.GrantorEntity{
Privilege: &milvuspb.PrivilegeEntity{Name: privilegeName},
User: &milvuspb.UserEntity{Name: entity.Grantor.User.Name},
})
} else if isExisted && funcutil.IsGrant(operateType) {
return nil
} else if !isExisted && funcutil.IsRevoke(operateType) {
return fmt.Errorf("fail to revoke the privilege because the privilege isn't granted for the role, key: /%s", k)
} else if isExisted && funcutil.IsRevoke(operateType) {
curGrantPrivilegeEntity.Entities = append(curGrantPrivilegeEntity.Entities[:dropIndex], curGrantPrivilegeEntity.Entities[dropIndex+1:]...)
}
}
if funcutil.IsRevoke(operateType) && len(curGrantPrivilegeEntity.Entities) == 0 {
err = kc.Txn.Remove(k)
if err != nil {
log.Error("fail to remove the grant privilege entity", zap.String("key", k), zap.Error(err))
return err
}
return nil
}
saveValue, err := proto.Marshal(curGrantPrivilegeEntity)
if err != nil {
log.Error("fail to marshal the grant privilege entity", zap.String("key", k), zap.Any("type", operateType), zap.Error(err))
return fmt.Errorf("fail to marshal grant info, key:%s, err:%w", k, err)
}
err = kc.Txn.Save(k, string(saveValue))
if err != nil {
log.Error("fail to save the grant privilege entity", zap.String("key", k), zap.Any("type", operateType), zap.Error(err))
return err
}
return nil
}
func (kc *Catalog) SelectGrant(ctx context.Context, tenant string, entity *milvuspb.GrantEntity) ([]*milvuspb.GrantEntity, error) {
var entities []*milvuspb.GrantEntity
var k string
appendGrantEntity := func(v string, object string, objectName string) error {
grantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{}
err := proto.Unmarshal([]byte(v), grantPrivilegeEntity)
if err != nil {
log.Error("fail to unmarshal the grant privilege entity", zap.String("key", k), zap.Error(err))
return err
}
for _, grantorEntity := range grantPrivilegeEntity.Entities {
entities = append(entities, &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: entity.Role.Name},
Object: &milvuspb.ObjectEntity{Name: object},
ObjectName: objectName,
Grantor: &milvuspb.GrantorEntity{
User: &milvuspb.UserEntity{Name: grantorEntity.User.Name},
Privilege: &milvuspb.PrivilegeEntity{Name: util.PrivilegeNameForAPI(grantorEntity.Privilege.Name)},
},
})
}
return nil
}
if !funcutil.IsEmptyString(entity.ObjectName) && entity.Object != nil && !funcutil.IsEmptyString(entity.Object.Name) {
k = funcutil.HandleTenantForEtcdKey(GranteePrefix, tenant, fmt.Sprintf("%s/%s/%s", entity.Role.Name, entity.Object.Name, entity.ObjectName))
v, err := kc.Txn.Load(k)
if err != nil {
log.Error("fail to load the grant privilege entity", zap.String("key", k), zap.Error(err))
return entities, err
}
err = appendGrantEntity(v, entity.Object.Name, entity.ObjectName)
if err != nil {
return entities, err
}
} else {
k = funcutil.HandleTenantForEtcdKey(GranteePrefix, tenant, entity.Role.Name)
keys, values, err := kc.Txn.LoadWithPrefix(k)
if err != nil {
log.Error("fail to load grant privilege entities", zap.String("key", k), zap.Error(err))
return entities, err
}
for i, key := range keys {
grantInfos := typeutil.AfterN(key, k+"/", "/")
if len(grantInfos) != 2 {
log.Warn("invalid grant key", zap.String("key", key))
continue
}
err = appendGrantEntity(values[i], grantInfos[0], grantInfos[1])
if err != nil {
return entities, err
}
}
}
return entities, nil
}
func (kc *Catalog) ListPolicy(ctx context.Context, tenant string) ([]string, error) {
var grantInfoStrs []string
k := funcutil.HandleTenantForEtcdKey(GranteePrefix, tenant, "")
keys, values, err := kc.Txn.LoadWithPrefix(k)
if err != nil {
log.Error("fail to load all grant privilege entities", zap.String("key", k), zap.Error(err))
return []string{}, err
}
for i, key := range keys {
grantInfos := typeutil.AfterN(key, k+"/", "/")
if len(grantInfos) != 3 {
log.Warn("invalid grant key", zap.String("key", key))
continue
}
grantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{}
err = proto.Unmarshal([]byte(values[i]), grantPrivilegeEntity)
if err != nil {
log.Warn("fail to unmarshal the grant privilege entity", zap.String("key", key), zap.Error(err))
continue
}
for _, grantorInfo := range grantPrivilegeEntity.Entities {
grantInfoStrs = append(grantInfoStrs,
funcutil.PolicyForPrivilege(grantInfos[0], grantInfos[1], grantInfos[2], grantorInfo.Privilege.Name))
}
}
return grantInfoStrs, nil
}
func (kc *Catalog) ListUserRole(ctx context.Context, tenant string) ([]string, error) {
var userRoles []string
k := funcutil.HandleTenantForEtcdKey(RoleMappingPrefix, tenant, "")
keys, _, err := kc.Txn.LoadWithPrefix(k)
if err != nil {
log.Error("fail to load all user-role mappings", zap.String("key", k), zap.Error(err))
return []string{}, err
}
for _, key := range keys {
userRolesInfos := typeutil.AfterN(key, k+"/", "/")
if len(userRolesInfos) != 2 {
log.Warn("invalid user-role key", zap.String("key", key))
continue
}
userRoles = append(userRoles, funcutil.EncodeUserRoleCache(userRolesInfos[0], userRolesInfos[1]))
}
return userRoles, nil
}
func (kc *Catalog) Close() {
// do nothing
}

View File

@ -16,9 +16,22 @@ const (
// CollectionAliasMetaPrefix prefix for collection alias meta
CollectionAliasMetaPrefix = ComponentPrefix + "/collection-alias"
// CommonCredentialPrefix subpath for common credential
/* #nosec G101 */
CommonCredentialPrefix = "/credential"
// UserSubPrefix subpath for credential user
UserSubPrefix = "/credential/users"
UserSubPrefix = CommonCredentialPrefix + "/users"
// CredentialPrefix prefix for credential user
CredentialPrefix = ComponentPrefix + UserSubPrefix
// RolePrefix prefix for role
RolePrefix = ComponentPrefix + CommonCredentialPrefix + "/roles"
// RoleMappingPrefix prefix for mapping between user and role
RoleMappingPrefix = ComponentPrefix + CommonCredentialPrefix + "/user-role-mapping"
// GranteePrefix prefix for mapping among user or role, resource type, resource name
GranteePrefix = ComponentPrefix + CommonCredentialPrefix + "/grantee-privileges"
)

View File

@ -72,6 +72,7 @@ const (
queryTypeLabelName = "query_type"
segmentStateLabelName = "segment_state"
usernameLabelName = "username"
rolenameLabelName = "role_name"
cacheNameLabelName = "cache_name"
cacheStateLabelName = "cache_state"
)

View File

@ -15,8 +15,6 @@ var (
Help: "number of proxy nodes managered by rootcoord",
}, []string{})
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// for time tick
@ -126,6 +124,15 @@ var (
Name: "credential_num",
Help: "number of credentials",
})
// RootCoordNumOfRoles counts the number of credentials.
RootCoordNumOfRoles = prometheus.NewGauge(
prometheus.GaugeOpts{
Namespace: milvusNamespace,
Subsystem: typeutil.RootCoordRole,
Name: "num_of_roles",
Help: "The number of roles",
})
)
//RegisterRootCoord registers RootCoord metrics
@ -154,4 +161,6 @@ func RegisterRootCoord(registry *prometheus.Registry) {
// for credential
registry.MustRegister(RootCoordNumOfCredentials)
registry.MustRegister(RootCoordNumOfRoles)
}

View File

@ -273,27 +273,28 @@ enum ImportState {
ImportAllocSegment = 10;
}
enum ResourceType {
enum ObjectType {
Collection = 0;
Global = 1;
}
enum ResourcePrivilege {
enum ObjectPrivilege {
PrivilegeAll = 0;
PrivilegeCreate = 1;
PrivilegeDrop = 2;
PrivilegeAlter = 3;
PrivilegeRead = 4;
PrivilegeCreateCollection = 1;
PrivilegeDropCollection = 2;
PrivilegeDescribeCollection = 3;
PrivilegeShowCollections = 4;
PrivilegeLoad = 5;
PrivilegeRelease = 6;
PrivilegeCompact = 7;
PrivilegeCompaction = 7;
PrivilegeInsert = 8;
PrivilegeDelete = 9;
}
message PrivilegeExt {
ResourceType resource_type = 1;
ResourcePrivilege resource_privilege = 2;
int32 resource_name_index = 3;
ObjectType object_type = 1;
ObjectPrivilege object_privilege = 2;
int32 object_name_index = 3;
}
extend google.protobuf.MessageOptions {

View File

@ -680,74 +680,77 @@ func (ImportState) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_555bd8c177793206, []int{8}
}
type ResourceType int32
type ObjectType int32
const (
ResourceType_Collection ResourceType = 0
ObjectType_Collection ObjectType = 0
ObjectType_Global ObjectType = 1
)
var ResourceType_name = map[int32]string{
var ObjectType_name = map[int32]string{
0: "Collection",
1: "Global",
}
var ResourceType_value = map[string]int32{
var ObjectType_value = map[string]int32{
"Collection": 0,
"Global": 1,
}
func (x ResourceType) String() string {
return proto.EnumName(ResourceType_name, int32(x))
func (x ObjectType) String() string {
return proto.EnumName(ObjectType_name, int32(x))
}
func (ResourceType) EnumDescriptor() ([]byte, []int) {
func (ObjectType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_555bd8c177793206, []int{9}
}
type ResourcePrivilege int32
type ObjectPrivilege int32
const (
ResourcePrivilege_PrivilegeAll ResourcePrivilege = 0
ResourcePrivilege_PrivilegeCreate ResourcePrivilege = 1
ResourcePrivilege_PrivilegeDrop ResourcePrivilege = 2
ResourcePrivilege_PrivilegeAlter ResourcePrivilege = 3
ResourcePrivilege_PrivilegeRead ResourcePrivilege = 4
ResourcePrivilege_PrivilegeLoad ResourcePrivilege = 5
ResourcePrivilege_PrivilegeRelease ResourcePrivilege = 6
ResourcePrivilege_PrivilegeCompact ResourcePrivilege = 7
ResourcePrivilege_PrivilegeInsert ResourcePrivilege = 8
ResourcePrivilege_PrivilegeDelete ResourcePrivilege = 9
ObjectPrivilege_PrivilegeAll ObjectPrivilege = 0
ObjectPrivilege_PrivilegeCreateCollection ObjectPrivilege = 1
ObjectPrivilege_PrivilegeDropCollection ObjectPrivilege = 2
ObjectPrivilege_PrivilegeDescribeCollection ObjectPrivilege = 3
ObjectPrivilege_PrivilegeShowCollections ObjectPrivilege = 4
ObjectPrivilege_PrivilegeLoad ObjectPrivilege = 5
ObjectPrivilege_PrivilegeRelease ObjectPrivilege = 6
ObjectPrivilege_PrivilegeCompaction ObjectPrivilege = 7
ObjectPrivilege_PrivilegeInsert ObjectPrivilege = 8
ObjectPrivilege_PrivilegeDelete ObjectPrivilege = 9
)
var ResourcePrivilege_name = map[int32]string{
var ObjectPrivilege_name = map[int32]string{
0: "PrivilegeAll",
1: "PrivilegeCreate",
2: "PrivilegeDrop",
3: "PrivilegeAlter",
4: "PrivilegeRead",
1: "PrivilegeCreateCollection",
2: "PrivilegeDropCollection",
3: "PrivilegeDescribeCollection",
4: "PrivilegeShowCollections",
5: "PrivilegeLoad",
6: "PrivilegeRelease",
7: "PrivilegeCompact",
7: "PrivilegeCompaction",
8: "PrivilegeInsert",
9: "PrivilegeDelete",
}
var ResourcePrivilege_value = map[string]int32{
"PrivilegeAll": 0,
"PrivilegeCreate": 1,
"PrivilegeDrop": 2,
"PrivilegeAlter": 3,
"PrivilegeRead": 4,
"PrivilegeLoad": 5,
"PrivilegeRelease": 6,
"PrivilegeCompact": 7,
"PrivilegeInsert": 8,
"PrivilegeDelete": 9,
var ObjectPrivilege_value = map[string]int32{
"PrivilegeAll": 0,
"PrivilegeCreateCollection": 1,
"PrivilegeDropCollection": 2,
"PrivilegeDescribeCollection": 3,
"PrivilegeShowCollections": 4,
"PrivilegeLoad": 5,
"PrivilegeRelease": 6,
"PrivilegeCompaction": 7,
"PrivilegeInsert": 8,
"PrivilegeDelete": 9,
}
func (x ResourcePrivilege) String() string {
return proto.EnumName(ResourcePrivilege_name, int32(x))
func (x ObjectPrivilege) String() string {
return proto.EnumName(ObjectPrivilege_name, int32(x))
}
func (ResourcePrivilege) EnumDescriptor() ([]byte, []int) {
func (ObjectPrivilege) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_555bd8c177793206, []int{10}
}
@ -1225,12 +1228,12 @@ func (m *DMLMsgHeader) GetShardName() string {
}
type PrivilegeExt struct {
ResourceType ResourceType `protobuf:"varint,1,opt,name=resource_type,json=resourceType,proto3,enum=milvus.proto.common.ResourceType" json:"resource_type,omitempty"`
ResourcePrivilege ResourcePrivilege `protobuf:"varint,2,opt,name=resource_privilege,json=resourcePrivilege,proto3,enum=milvus.proto.common.ResourcePrivilege" json:"resource_privilege,omitempty"`
ResourceNameIndex int32 `protobuf:"varint,3,opt,name=resource_name_index,json=resourceNameIndex,proto3" json:"resource_name_index,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
ObjectType ObjectType `protobuf:"varint,1,opt,name=object_type,json=objectType,proto3,enum=milvus.proto.common.ObjectType" json:"object_type,omitempty"`
ObjectPrivilege ObjectPrivilege `protobuf:"varint,2,opt,name=object_privilege,json=objectPrivilege,proto3,enum=milvus.proto.common.ObjectPrivilege" json:"object_privilege,omitempty"`
ObjectNameIndex int32 `protobuf:"varint,3,opt,name=object_name_index,json=objectNameIndex,proto3" json:"object_name_index,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PrivilegeExt) Reset() { *m = PrivilegeExt{} }
@ -1258,23 +1261,23 @@ func (m *PrivilegeExt) XXX_DiscardUnknown() {
var xxx_messageInfo_PrivilegeExt proto.InternalMessageInfo
func (m *PrivilegeExt) GetResourceType() ResourceType {
func (m *PrivilegeExt) GetObjectType() ObjectType {
if m != nil {
return m.ResourceType
return m.ObjectType
}
return ResourceType_Collection
return ObjectType_Collection
}
func (m *PrivilegeExt) GetResourcePrivilege() ResourcePrivilege {
func (m *PrivilegeExt) GetObjectPrivilege() ObjectPrivilege {
if m != nil {
return m.ResourcePrivilege
return m.ObjectPrivilege
}
return ResourcePrivilege_PrivilegeAll
return ObjectPrivilege_PrivilegeAll
}
func (m *PrivilegeExt) GetResourceNameIndex() int32 {
func (m *PrivilegeExt) GetObjectNameIndex() int32 {
if m != nil {
return m.ResourceNameIndex
return m.ObjectNameIndex
}
return 0
}
@ -1298,8 +1301,8 @@ func init() {
proto.RegisterEnum("milvus.proto.common.CompactionState", CompactionState_name, CompactionState_value)
proto.RegisterEnum("milvus.proto.common.ConsistencyLevel", ConsistencyLevel_name, ConsistencyLevel_value)
proto.RegisterEnum("milvus.proto.common.ImportState", ImportState_name, ImportState_value)
proto.RegisterEnum("milvus.proto.common.ResourceType", ResourceType_name, ResourceType_value)
proto.RegisterEnum("milvus.proto.common.ResourcePrivilege", ResourcePrivilege_name, ResourcePrivilege_value)
proto.RegisterEnum("milvus.proto.common.ObjectType", ObjectType_name, ObjectType_value)
proto.RegisterEnum("milvus.proto.common.ObjectPrivilege", ObjectPrivilege_name, ObjectPrivilege_value)
proto.RegisterType((*Status)(nil), "milvus.proto.common.Status")
proto.RegisterType((*KeyValuePair)(nil), "milvus.proto.common.KeyValuePair")
proto.RegisterType((*KeyDataPair)(nil), "milvus.proto.common.KeyDataPair")
@ -1317,150 +1320,152 @@ func init() {
func init() { proto.RegisterFile("common.proto", fileDescriptor_555bd8c177793206) }
var fileDescriptor_555bd8c177793206 = []byte{
// 2318 bytes of a gzipped FileDescriptorProto
// 2342 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x49, 0x73, 0x24, 0x47,
0x15, 0x56, 0xa9, 0x7b, 0xd4, 0xea, 0xec, 0x92, 0x94, 0x93, 0x9a, 0xd1, 0xc8, 0xe3, 0xb1, 0x2d,
0x37, 0xb6, 0x11, 0x02, 0x4b, 0x60, 0x47, 0x00, 0x41, 0x84, 0x89, 0x90, 0xba, 0x25, 0x4d, 0x87,
0xb5, 0x34, 0x25, 0xc9, 0x76, 0x10, 0x01, 0x8a, 0x54, 0xd5, 0x53, 0xab, 0x3c, 0x55, 0x95, 0x45,
0x66, 0xb6, 0x46, 0xcd, 0xc9, 0x98, 0x3f, 0x00, 0xe6, 0x0f, 0xf0, 0x03, 0xd8, 0x17, 0xc3, 0x91,
0x1d, 0x9b, 0xed, 0xc2, 0x85, 0xcd, 0xc0, 0x11, 0xee, 0xac, 0x5e, 0x89, 0x97, 0x59, 0x9b, 0x64,
0x19, 0x0e, 0xdc, 0x2a, 0xbf, 0xf7, 0xf2, 0x6d, 0xf9, 0x96, 0xcc, 0x22, 0xae, 0x2f, 0xe2, 0x58,
0x24, 0xcb, 0xa9, 0x14, 0x5a, 0xb0, 0xd9, 0x38, 0x8c, 0x4e, 0x87, 0xca, 0xae, 0x96, 0x2d, 0xe9,
0xe6, 0xc2, 0x40, 0x88, 0x41, 0x04, 0x2b, 0x06, 0x3c, 0x1a, 0x1e, 0xaf, 0x04, 0xa0, 0x7c, 0x19,
0xa6, 0x5a, 0x48, 0xcb, 0xd8, 0x3e, 0x24, 0x13, 0x7b, 0x9a, 0xeb, 0xa1, 0x62, 0x4f, 0x10, 0x02,
0x52, 0x0a, 0x79, 0xe8, 0x8b, 0x00, 0xe6, 0x9d, 0x05, 0x67, 0x71, 0xfa, 0xb1, 0xfb, 0x97, 0x2f,
0x91, 0xba, 0xbc, 0x8e, 0x6c, 0x1d, 0x11, 0x80, 0xd7, 0x84, 0xfc, 0x93, 0xcd, 0x91, 0x09, 0x09,
0x5c, 0x89, 0x64, 0x7e, 0x7c, 0xc1, 0x59, 0x6c, 0x7a, 0xd9, 0xaa, 0xfd, 0x41, 0xe2, 0x3e, 0x09,
0xa3, 0xa7, 0x78, 0x34, 0x84, 0x3e, 0x0f, 0x25, 0xa3, 0xa4, 0x76, 0x07, 0x46, 0x46, 0x7e, 0xd3,
0xc3, 0x4f, 0x76, 0x8d, 0x5c, 0x39, 0x45, 0x72, 0xb6, 0xd1, 0x2e, 0xda, 0x8f, 0x93, 0xd6, 0x93,
0x30, 0xea, 0x72, 0xcd, 0xdf, 0x61, 0x1b, 0x23, 0xf5, 0x80, 0x6b, 0x6e, 0x76, 0xb9, 0x9e, 0xf9,
0x6e, 0xdf, 0x22, 0xf5, 0xb5, 0x48, 0x1c, 0x95, 0x22, 0x1d, 0x43, 0xcc, 0x44, 0x9e, 0x12, 0xda,
0x8f, 0xb8, 0x0f, 0x27, 0x22, 0x0a, 0x40, 0x1a, 0x93, 0x50, 0xae, 0xe6, 0x83, 0x5c, 0xae, 0xe6,
0x03, 0xf6, 0x61, 0x52, 0xd7, 0xa3, 0xd4, 0x5a, 0x33, 0xfd, 0xd8, 0x43, 0x97, 0x46, 0xa0, 0x22,
0x66, 0x7f, 0x94, 0x82, 0x67, 0x76, 0x60, 0x08, 0x8c, 0x22, 0x35, 0x5f, 0x5b, 0xa8, 0x2d, 0xba,
0x5e, 0xb6, 0x6a, 0x7f, 0xe2, 0x9c, 0xde, 0x4d, 0x29, 0x86, 0x29, 0xeb, 0x11, 0x37, 0x2d, 0x31,
0x35, 0xef, 0x2c, 0xd4, 0x16, 0x5b, 0x8f, 0x3d, 0xfc, 0xbf, 0xb4, 0x19, 0xa3, 0xbd, 0x73, 0x5b,
0xdb, 0x8f, 0x92, 0xc6, 0x6a, 0x10, 0x48, 0x50, 0x8a, 0x4d, 0x93, 0xf1, 0x30, 0xcd, 0x9c, 0x19,
0x0f, 0x53, 0x8c, 0x51, 0x2a, 0xa4, 0x36, 0xbe, 0xd4, 0x3c, 0xf3, 0xdd, 0x7e, 0xc1, 0x21, 0x8d,
0x6d, 0x35, 0x58, 0xe3, 0x0a, 0xd8, 0x87, 0xc8, 0x64, 0xac, 0x06, 0x87, 0xc6, 0x5f, 0x7b, 0xe2,
0xb7, 0x2e, 0xb5, 0x60, 0x5b, 0x0d, 0x8c, 0x9f, 0x8d, 0xd8, 0x7e, 0x60, 0x80, 0x63, 0x35, 0xe8,
0x75, 0x33, 0xc9, 0x76, 0xc1, 0x6e, 0x91, 0xa6, 0x0e, 0x63, 0x50, 0x9a, 0xc7, 0xe9, 0x7c, 0x6d,
0xc1, 0x59, 0xac, 0x7b, 0x25, 0xc0, 0x6e, 0x92, 0x49, 0x25, 0x86, 0xd2, 0x87, 0x5e, 0x77, 0xbe,
0x6e, 0xb6, 0x15, 0xeb, 0xf6, 0x13, 0xa4, 0xb9, 0xad, 0x06, 0xb7, 0x81, 0x07, 0x20, 0xd9, 0xfb,
0x49, 0xfd, 0x88, 0x2b, 0x6b, 0x51, 0xeb, 0x9d, 0x2d, 0x42, 0x0f, 0x3c, 0xc3, 0xd9, 0xfe, 0x24,
0x71, 0xbb, 0xdb, 0x5b, 0xff, 0x87, 0x04, 0x34, 0x5d, 0x9d, 0x70, 0x19, 0xec, 0xf0, 0x38, 0x4f,
0xc4, 0x12, 0x68, 0xbf, 0xe2, 0x10, 0xb7, 0x2f, 0xc3, 0xd3, 0x30, 0x82, 0x01, 0xac, 0x9f, 0x69,
0xb6, 0x41, 0xa6, 0x24, 0x58, 0xeb, 0xab, 0xd1, 0x7b, 0xf0, 0x52, 0x4d, 0x5e, 0xc6, 0x69, 0x42,
0xe8, 0xca, 0xca, 0x8a, 0x1d, 0x10, 0x56, 0xc8, 0x49, 0x73, 0x05, 0x59, 0xea, 0x3d, 0xf2, 0x5f,
0x85, 0x15, 0xe6, 0x78, 0x57, 0xe5, 0x45, 0x88, 0x2d, 0x93, 0xd9, 0x42, 0x6c, 0xc2, 0x63, 0x38,
0x0c, 0x93, 0x00, 0xce, 0xcc, 0x91, 0x5c, 0x29, 0xf9, 0xd1, 0xb5, 0x1e, 0x12, 0x96, 0x7e, 0x3d,
0x49, 0x9a, 0x45, 0x55, 0xb3, 0x16, 0x69, 0xec, 0x0d, 0x7d, 0x1f, 0x94, 0xa2, 0x63, 0x6c, 0x96,
0xcc, 0x1c, 0x24, 0x70, 0x96, 0x82, 0xaf, 0x21, 0x30, 0x3c, 0xd4, 0x61, 0x57, 0xc9, 0x54, 0x47,
0x24, 0x09, 0xf8, 0x7a, 0x83, 0x87, 0x11, 0x04, 0x74, 0x9c, 0x5d, 0x23, 0xb4, 0x0f, 0x32, 0x0e,
0x95, 0x0a, 0x45, 0xd2, 0x85, 0x24, 0x84, 0x80, 0xd6, 0xd8, 0x0d, 0x32, 0xdb, 0x11, 0x51, 0x04,
0xbe, 0x0e, 0x45, 0xb2, 0x23, 0xf4, 0xfa, 0x59, 0xa8, 0xb4, 0xa2, 0x75, 0x14, 0xdb, 0x8b, 0x22,
0x18, 0xf0, 0x68, 0x55, 0x0e, 0x86, 0x31, 0x24, 0x9a, 0x5e, 0x41, 0x19, 0x19, 0xd8, 0x0d, 0x63,
0x48, 0x50, 0x12, 0x6d, 0x54, 0x50, 0x63, 0x2c, 0xc6, 0x8d, 0x4e, 0xb2, 0x7b, 0xc8, 0xf5, 0x0c,
0xad, 0x28, 0xe0, 0x31, 0xd0, 0x26, 0x9b, 0x21, 0xad, 0x8c, 0xb4, 0xbf, 0xdb, 0x7f, 0x92, 0x92,
0x8a, 0x04, 0x4f, 0xdc, 0xf5, 0xc0, 0x17, 0x32, 0xa0, 0xad, 0x8a, 0x09, 0x4f, 0x81, 0xaf, 0x85,
0xec, 0x75, 0xa9, 0x8b, 0x06, 0x67, 0xe0, 0x1e, 0x70, 0xe9, 0x9f, 0x78, 0xa0, 0x86, 0x91, 0xa6,
0x53, 0x8c, 0x12, 0x77, 0x23, 0x8c, 0x60, 0x47, 0xe8, 0x0d, 0x31, 0x4c, 0x02, 0x3a, 0xcd, 0xa6,
0x09, 0xd9, 0x06, 0xcd, 0xb3, 0x08, 0xcc, 0xa0, 0xda, 0x0e, 0xf7, 0x4f, 0x20, 0x03, 0x28, 0x9b,
0x23, 0xac, 0xc3, 0x93, 0x44, 0xe8, 0x8e, 0x04, 0xae, 0x61, 0xc3, 0xd4, 0x2b, 0xbd, 0x8a, 0xe6,
0x9c, 0xc3, 0xc3, 0x08, 0x28, 0x2b, 0xb9, 0xbb, 0x10, 0x41, 0xc1, 0x3d, 0x5b, 0x72, 0x67, 0x38,
0x72, 0x5f, 0x43, 0xe3, 0xd7, 0x86, 0x61, 0x14, 0x98, 0x90, 0xd8, 0x63, 0xb9, 0x8e, 0x36, 0x66,
0xc6, 0xef, 0x6c, 0xf5, 0xf6, 0xf6, 0xe9, 0x1c, 0xbb, 0x4e, 0xae, 0x66, 0xc8, 0x36, 0x68, 0x19,
0xfa, 0x26, 0x78, 0x37, 0xd0, 0xd4, 0xdd, 0xa1, 0xde, 0x3d, 0xde, 0x86, 0x58, 0xc8, 0x11, 0x9d,
0xc7, 0x03, 0x35, 0x92, 0xf2, 0x23, 0xa2, 0xf7, 0xa0, 0x86, 0xf5, 0x38, 0xd5, 0xa3, 0x32, 0xbc,
0xf4, 0x26, 0xbb, 0x97, 0xdc, 0x38, 0x48, 0x03, 0xae, 0xa1, 0x17, 0x63, 0x33, 0xd9, 0xe7, 0xea,
0x0e, 0xba, 0x3b, 0x94, 0x40, 0xef, 0x65, 0x37, 0xc9, 0xdc, 0xf9, 0xb3, 0x28, 0x82, 0x75, 0x0b,
0x37, 0x5a, 0x6f, 0x3b, 0x12, 0x02, 0x48, 0x74, 0xc8, 0xa3, 0x7c, 0xe3, 0x7d, 0xa5, 0xd4, 0xb7,
0x13, 0xef, 0x47, 0xa2, 0xf5, 0xfc, 0xed, 0xc4, 0x07, 0xd8, 0x3c, 0xb9, 0xb6, 0x09, 0xfa, 0xed,
0x94, 0x05, 0xa4, 0x6c, 0x85, 0xca, 0x90, 0x0e, 0x14, 0x48, 0x95, 0x53, 0x1e, 0x64, 0x8c, 0x4c,
0x6f, 0x82, 0x46, 0x30, 0xc7, 0xda, 0x18, 0x27, 0x6b, 0x9e, 0x27, 0x22, 0xc8, 0xe1, 0x77, 0x61,
0x0c, 0xba, 0x52, 0xa4, 0x55, 0xf0, 0x21, 0x74, 0x73, 0x37, 0x05, 0xc9, 0x35, 0xa0, 0x8c, 0x2a,
0xed, 0x61, 0x94, 0xb3, 0x07, 0x18, 0x81, 0x2a, 0xfc, 0x48, 0x09, 0x57, 0xb5, 0xbe, 0x1b, 0x73,
0x38, 0xe3, 0xce, 0x2a, 0x32, 0x27, 0x2d, 0xa2, 0xd7, 0x99, 0x92, 0xa2, 0xaa, 0x73, 0xe2, 0x7b,
0x30, 0x55, 0xec, 0xbe, 0x4d, 0xc9, 0x13, 0x9d, 0xe3, 0x4b, 0xec, 0x41, 0x72, 0x9f, 0x07, 0xc7,
0x12, 0xd4, 0x49, 0x5f, 0x44, 0xa1, 0x3f, 0xea, 0x25, 0xc7, 0xa2, 0x48, 0x49, 0x64, 0x79, 0x2f,
0x5a, 0x82, 0x61, 0xb1, 0xf4, 0x1c, 0x7e, 0x1f, 0xc6, 0x64, 0x47, 0xe8, 0x3d, 0x6c, 0x78, 0x5b,
0xa6, 0x85, 0xd2, 0x47, 0x51, 0xcb, 0x8e, 0xf0, 0x20, 0x8d, 0x42, 0x9f, 0xaf, 0x9e, 0xf2, 0x30,
0xe2, 0x47, 0x11, 0xd0, 0x65, 0x0c, 0xca, 0x1e, 0x0c, 0xb0, 0x64, 0x8b, 0xf3, 0x5d, 0x61, 0x8c,
0x4c, 0x75, 0xbb, 0x1e, 0x7c, 0x6a, 0x08, 0x4a, 0x7b, 0xdc, 0x07, 0xfa, 0x97, 0xc6, 0xd2, 0x33,
0x84, 0x98, 0xa4, 0xc2, 0x0b, 0x06, 0xa0, 0x8a, 0x72, 0xb5, 0x23, 0x12, 0xa0, 0x63, 0xcc, 0x25,
0x93, 0x07, 0x49, 0xa8, 0xd4, 0x10, 0x02, 0xea, 0x60, 0x41, 0xf5, 0x92, 0xbe, 0x14, 0x03, 0x9c,
0x65, 0x74, 0x1c, 0xa9, 0x1b, 0x61, 0x12, 0xaa, 0x13, 0xd3, 0x4a, 0x08, 0x99, 0xc8, 0x2a, 0xab,
0xbe, 0xf4, 0xbc, 0x43, 0xdc, 0xcc, 0x06, 0x2b, 0xfc, 0x1a, 0xa1, 0xd5, 0x75, 0x29, 0xbe, 0x48,
0x68, 0x07, 0xdb, 0xda, 0xa6, 0x14, 0x77, 0xc3, 0x64, 0x40, 0xc7, 0x51, 0xda, 0x1e, 0xf0, 0xc8,
0x48, 0x6e, 0x91, 0xc6, 0x46, 0x34, 0x34, 0x6a, 0xea, 0x46, 0x29, 0x2e, 0x90, 0xed, 0x0a, 0x92,
0x30, 0x01, 0x52, 0x08, 0xe8, 0x04, 0x9b, 0x22, 0x4d, 0x9b, 0xf6, 0x48, 0x6b, 0x2c, 0x7d, 0x94,
0xcc, 0x5c, 0xb8, 0x07, 0xb0, 0x49, 0x52, 0xcf, 0x54, 0x53, 0xe2, 0xae, 0x85, 0x09, 0x97, 0x23,
0xdb, 0x5b, 0x68, 0x80, 0x35, 0xb7, 0x11, 0x09, 0xae, 0x33, 0x00, 0x96, 0x5e, 0x74, 0xcd, 0x20,
0x36, 0x1b, 0xa7, 0x48, 0xf3, 0x20, 0x09, 0xe0, 0x38, 0x4c, 0x20, 0xa0, 0x63, 0xa6, 0xe6, 0x6d,
0xb5, 0x94, 0xc5, 0x17, 0x60, 0x04, 0xd1, 0x98, 0x0a, 0x06, 0x58, 0xb8, 0xb7, 0xb9, 0xaa, 0x40,
0xc7, 0x78, 0x6e, 0x5d, 0x73, 0xcd, 0x3b, 0xaa, 0x6e, 0x1f, 0x98, 0x73, 0x3b, 0x11, 0x77, 0x4b,
0x4c, 0xd1, 0x13, 0xd4, 0xb4, 0x09, 0x7a, 0x6f, 0xa4, 0x34, 0xc4, 0x1d, 0x91, 0x1c, 0x87, 0x03,
0x45, 0x43, 0xd4, 0xb4, 0x25, 0x78, 0x50, 0xd9, 0xfe, 0x2c, 0x66, 0x8e, 0x07, 0x11, 0x70, 0x55,
0x95, 0x7a, 0xc7, 0x74, 0x3d, 0x63, 0xea, 0x6a, 0x14, 0x72, 0x45, 0x23, 0x74, 0x05, 0xad, 0xb4,
0xcb, 0x18, 0x0f, 0x75, 0x35, 0xd2, 0x20, 0xed, 0x3a, 0x61, 0xd7, 0xc8, 0x8c, 0xe5, 0xef, 0x73,
0xa9, 0x43, 0x23, 0xe4, 0x25, 0xc7, 0xa4, 0x8f, 0x14, 0x69, 0x89, 0xbd, 0x8c, 0x43, 0xc6, 0xbd,
0xcd, 0x55, 0x09, 0xfd, 0xcc, 0x61, 0x73, 0xe4, 0x6a, 0xee, 0x5a, 0x89, 0xff, 0xdc, 0x61, 0xb3,
0x64, 0x1a, 0x5d, 0x2b, 0x30, 0x45, 0x7f, 0x61, 0x40, 0x74, 0xa2, 0x02, 0xfe, 0xd2, 0x48, 0xc8,
0xbc, 0xa8, 0xe0, 0xbf, 0x32, 0xca, 0x50, 0x42, 0x96, 0x44, 0x8a, 0xbe, 0xea, 0xa0, 0xa5, 0xb9,
0xb2, 0x0c, 0xa6, 0xaf, 0x19, 0x46, 0x94, 0x5a, 0x30, 0xbe, 0x6e, 0x18, 0x33, 0x99, 0x05, 0xfa,
0x86, 0x41, 0x6f, 0xf3, 0x24, 0x10, 0xc7, 0xc7, 0x05, 0xfa, 0xa6, 0xc3, 0xe6, 0xc9, 0x2c, 0x6e,
0x5f, 0xe3, 0x11, 0x4f, 0xfc, 0x92, 0xff, 0x2d, 0x87, 0x5d, 0x27, 0xf4, 0x82, 0x3a, 0x45, 0x9f,
0x1b, 0x67, 0x34, 0x8f, 0xaf, 0x29, 0x1e, 0xfa, 0xa5, 0x71, 0x13, 0xab, 0x8c, 0xd1, 0x62, 0x5f,
0x1e, 0x67, 0xd3, 0x36, 0xe8, 0x76, 0xfd, 0x95, 0x71, 0xd6, 0x22, 0x13, 0xbd, 0x44, 0x81, 0xd4,
0xf4, 0x73, 0x98, 0xdf, 0x13, 0xb6, 0x83, 0xd2, 0xcf, 0x63, 0x19, 0x5d, 0x31, 0xf9, 0x4d, 0x5f,
0xc0, 0xe9, 0xcc, 0x3c, 0x50, 0x90, 0x04, 0x95, 0xda, 0x51, 0xf4, 0x0b, 0x66, 0x87, 0x1d, 0x7f,
0xf4, 0x6f, 0x35, 0x13, 0x9a, 0xea, 0x2c, 0xfc, 0x7b, 0x0d, 0x4d, 0xd8, 0x04, 0x5d, 0x96, 0x33,
0xfd, 0x47, 0x8d, 0xdd, 0x24, 0xd7, 0x73, 0xcc, 0x4c, 0xa6, 0xa2, 0x90, 0xff, 0x59, 0x63, 0xb7,
0xc8, 0x0d, 0x6c, 0xd3, 0x45, 0xde, 0xe0, 0xa6, 0x50, 0xe9, 0xd0, 0x57, 0xf4, 0x5f, 0x35, 0x76,
0x2f, 0x99, 0xdb, 0x04, 0x5d, 0x9c, 0x47, 0x85, 0xf8, 0xef, 0x1a, 0x9b, 0x22, 0x93, 0x1e, 0x8e,
0x2e, 0x38, 0x05, 0xfa, 0x6a, 0x0d, 0x0f, 0x35, 0x5f, 0x66, 0xe6, 0xbc, 0x56, 0xc3, 0x50, 0x3f,
0xcd, 0xb5, 0x7f, 0xd2, 0x8d, 0x3b, 0x27, 0x3c, 0x49, 0x20, 0x52, 0xf4, 0xf5, 0x1a, 0x06, 0xd4,
0x83, 0x58, 0x9c, 0x42, 0x05, 0x7e, 0xc3, 0x38, 0x6d, 0x98, 0x3f, 0x36, 0x04, 0x39, 0x2a, 0x08,
0x6f, 0xd6, 0xf0, 0x68, 0x2c, 0xff, 0x79, 0xca, 0x5b, 0x35, 0x76, 0x1f, 0x99, 0xb7, 0xcd, 0x22,
0x3f, 0x18, 0x24, 0x0e, 0x00, 0xdb, 0x2b, 0x7d, 0xae, 0x5e, 0x48, 0xec, 0x42, 0xa4, 0x79, 0xb1,
0xef, 0x33, 0x75, 0xb4, 0x0b, 0x8b, 0xab, 0xec, 0xaa, 0x8a, 0x3e, 0x5f, 0xc7, 0x13, 0xdd, 0x04,
0x9d, 0x35, 0x56, 0x45, 0x3f, 0x6b, 0x90, 0x4c, 0xb2, 0x11, 0xf9, 0x9b, 0x3a, 0x9b, 0x21, 0xc4,
0xd6, 0xa4, 0x01, 0x7e, 0x9b, 0x8b, 0xc2, 0xbb, 0xcb, 0x29, 0x48, 0xd3, 0xd8, 0xe9, 0xef, 0x0a,
0x05, 0x95, 0xce, 0x47, 0x7f, 0x5f, 0xc7, 0x90, 0xed, 0x87, 0x31, 0xec, 0x87, 0xfe, 0x1d, 0xfa,
0xb5, 0x26, 0x86, 0xcc, 0x78, 0xb4, 0x23, 0x02, 0xb0, 0x27, 0xfc, 0xf5, 0x26, 0x26, 0x0c, 0xe6,
0xa1, 0x4d, 0x98, 0x6f, 0x98, 0x75, 0xd6, 0xbd, 0x7b, 0x5d, 0xfa, 0x4d, 0xbc, 0x43, 0x91, 0x6c,
0xbd, 0xbf, 0xb7, 0x4b, 0xbf, 0xd5, 0x44, 0x55, 0xab, 0x51, 0x24, 0x7c, 0xae, 0x8b, 0x6a, 0xf8,
0x76, 0x13, 0xcb, 0xa9, 0xa2, 0x3d, 0x3b, 0xb5, 0x17, 0x9b, 0x18, 0xfb, 0x0c, 0x37, 0xc9, 0xd6,
0xc5, 0xa6, 0xf8, 0x1d, 0x23, 0x15, 0x5f, 0x74, 0x68, 0xc9, 0xbe, 0xa6, 0xdf, 0x35, 0x7c, 0x17,
0xaf, 0x05, 0xf4, 0x0f, 0xad, 0x2c, 0xbf, 0x2a, 0xd8, 0x2b, 0x2d, 0x5b, 0x1f, 0xe7, 0xef, 0x01,
0xf4, 0x8f, 0x06, 0xbe, 0x78, 0x77, 0xa0, 0x7f, 0x6a, 0xa1, 0x61, 0xd5, 0xf1, 0x8f, 0x97, 0x60,
0x45, 0xff, 0xdc, 0x42, 0x0b, 0xca, 0x41, 0x4f, 0xbf, 0xe7, 0x62, 0xb0, 0xf2, 0x11, 0x4f, 0xbf,
0xef, 0xa2, 0x9b, 0x17, 0x86, 0x3b, 0xfd, 0x81, 0x6b, 0x8e, 0xa3, 0x18, 0xeb, 0xf4, 0x87, 0x15,
0x00, 0xb9, 0xe8, 0x8f, 0x5c, 0xd3, 0x81, 0xce, 0x8d, 0x72, 0xfa, 0x63, 0x17, 0x6d, 0xbb, 0x38,
0xc4, 0xe9, 0x4f, 0x5c, 0x7b, 0xdc, 0xc5, 0xf8, 0xa6, 0x3f, 0x75, 0xb1, 0x02, 0x2e, 0x1f, 0xdc,
0xf4, 0x25, 0xa3, 0xab, 0x1c, 0xd9, 0xf4, 0x65, 0x77, 0xa9, 0x4d, 0x1a, 0x5d, 0x15, 0x99, 0xb9,
0xd1, 0x20, 0xb5, 0xae, 0x8a, 0xe8, 0x18, 0xb6, 0xd9, 0x35, 0x21, 0xa2, 0xf5, 0xb3, 0x54, 0x3e,
0xf5, 0x01, 0xea, 0x2c, 0xad, 0x91, 0x99, 0x8e, 0x88, 0x53, 0x5e, 0x94, 0x9b, 0x19, 0x15, 0x76,
0xc6, 0x40, 0x60, 0x53, 0x65, 0x0c, 0x7b, 0xf5, 0xfa, 0x19, 0xf8, 0x43, 0x33, 0xd1, 0x1c, 0x5c,
0xe2, 0x26, 0x0c, 0x72, 0x40, 0xc7, 0x97, 0x9e, 0x21, 0xb4, 0x23, 0x12, 0x15, 0x2a, 0x0d, 0x89,
0x3f, 0xda, 0x82, 0x53, 0x88, 0xcc, 0xdc, 0xd4, 0x52, 0x24, 0x03, 0x3a, 0x66, 0xde, 0x09, 0x60,
0xee, 0xfb, 0x76, 0xba, 0xae, 0xe1, 0x5d, 0xc0, 0x3c, 0x06, 0xa6, 0x09, 0x59, 0x3f, 0x85, 0x44,
0x0f, 0x79, 0x14, 0x8d, 0x68, 0x0d, 0xd7, 0x9d, 0xa1, 0xd2, 0x22, 0x0e, 0x3f, 0x6d, 0xe6, 0xf7,
0x57, 0x1d, 0xd2, 0xb2, 0xa3, 0xb4, 0x30, 0xcd, 0x2e, 0xfb, 0x90, 0x04, 0xa1, 0x11, 0x8e, 0x77,
0x59, 0x03, 0x65, 0x43, 0xdf, 0x29, 0x99, 0xf6, 0x34, 0x97, 0x3a, 0x7f, 0x74, 0x58, 0xa8, 0x2b,
0xee, 0x26, 0x91, 0xe0, 0x81, 0x99, 0xe7, 0xc5, 0xd6, 0x3e, 0x97, 0xca, 0x0c, 0x75, 0xbc, 0xea,
0x67, 0xf2, 0xa5, 0xf1, 0x27, 0xa0, 0x57, 0x4a, 0xb0, 0xf4, 0x79, 0x02, 0x87, 0xa7, 0x05, 0x4d,
0xb2, 0xe7, 0x99, 0x4e, 0x96, 0xee, 0x27, 0x6e, 0xf5, 0x19, 0x67, 0x3c, 0x2a, 0xc7, 0xe0, 0xd8,
0xd2, 0x2b, 0x0e, 0x0e, 0x96, 0x8b, 0xef, 0x30, 0x5a, 0x79, 0x36, 0xae, 0x46, 0x91, 0x7d, 0x4e,
0x15, 0x88, 0x4d, 0x44, 0xeb, 0x59, 0x01, 0x62, 0x32, 0x52, 0x6c, 0xf2, 0xd3, 0x95, 0x9d, 0x1a,
0x24, 0xad, 0x9d, 0x63, 0xf3, 0x80, 0xa3, 0x63, 0x55, 0x08, 0xeb, 0xd9, 0x3e, 0xa2, 0x2a, 0x5c,
0x66, 0x2c, 0xd1, 0x89, 0x73, 0x68, 0x96, 0x18, 0xb4, 0x71, 0xce, 0x9a, 0x6c, 0x5e, 0x4c, 0x9e,
0x03, 0xb3, 0xb9, 0xd1, 0xfc, 0x88, 0x20, 0x57, 0x8b, 0xf7, 0xe9, 0x21, 0x9c, 0xe9, 0x43, 0x71,
0xf4, 0x2c, 0x7b, 0x60, 0xd9, 0xfe, 0x5f, 0x5a, 0xce, 0xff, 0x2f, 0x2d, 0x6f, 0x83, 0x52, 0x7c,
0x00, 0xbb, 0xa9, 0x19, 0xac, 0xf3, 0x7f, 0x6d, 0x98, 0x07, 0xf8, 0xe5, 0xcf, 0xe2, 0xea, 0x83,
0xda, 0x9b, 0x49, 0x2b, 0xab, 0xdd, 0xa3, 0x67, 0xd7, 0x9e, 0x26, 0xd3, 0xa1, 0xc8, 0xf7, 0x0d,
0x64, 0xea, 0xaf, 0xb5, 0x3a, 0x66, 0x5f, 0x1f, 0x65, 0xf4, 0x9d, 0x8f, 0x3f, 0x3e, 0x08, 0xf5,
0xc9, 0xf0, 0x08, 0xa5, 0xad, 0x58, 0xb6, 0x47, 0x43, 0x91, 0x7d, 0xad, 0x84, 0x89, 0xc6, 0xa2,
0x8f, 0xec, 0x9f, 0xaf, 0x15, 0xab, 0x31, 0x3d, 0xfa, 0xa2, 0xe3, 0x1c, 0x4d, 0x18, 0xe8, 0xf1,
0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe3, 0xd2, 0xcb, 0x48, 0x3f, 0x13, 0x00, 0x00,
0xf5, 0x57, 0x75, 0xf7, 0xa8, 0xd5, 0xd9, 0x2d, 0x29, 0x95, 0xd2, 0x68, 0xda, 0xb3, 0x78, 0xe4,
0xfe, 0xdb, 0x7f, 0x44, 0x83, 0x25, 0xb0, 0x23, 0x80, 0x20, 0xc2, 0x04, 0x52, 0xb7, 0xa4, 0xe9,
0xb0, 0x96, 0xa6, 0xa4, 0x19, 0x3b, 0x88, 0x00, 0x45, 0x76, 0xd5, 0x53, 0xab, 0x66, 0xaa, 0x2a,
0x8b, 0xca, 0x6c, 0x8d, 0x9a, 0x93, 0x31, 0x37, 0x4e, 0x60, 0xbe, 0x00, 0x1f, 0x80, 0x7d, 0x31,
0x1c, 0xd9, 0xb1, 0x01, 0x73, 0xe1, 0xc2, 0x0e, 0x47, 0xb8, 0xb3, 0x7a, 0x25, 0x5e, 0x66, 0x6d,
0xd2, 0xc8, 0x70, 0xe0, 0x56, 0xf9, 0x7b, 0x2f, 0xdf, 0x96, 0x6f, 0xc9, 0x2c, 0xd2, 0x70, 0x44,
0x10, 0x88, 0x70, 0x25, 0x8a, 0x85, 0x12, 0x6c, 0x3e, 0xf0, 0xfc, 0x93, 0x91, 0x34, 0xab, 0x15,
0x43, 0xba, 0xba, 0x34, 0x14, 0x62, 0xe8, 0xc3, 0xaa, 0x06, 0x07, 0xa3, 0xa3, 0x55, 0x17, 0xa4,
0x13, 0x7b, 0x91, 0x12, 0xb1, 0x61, 0x6c, 0x1d, 0x92, 0xc9, 0x7d, 0xc5, 0xd5, 0x48, 0xb2, 0xa7,
0x08, 0x81, 0x38, 0x16, 0xf1, 0xa1, 0x23, 0x5c, 0x68, 0x5a, 0x4b, 0xd6, 0xf2, 0xcc, 0x13, 0x0f,
0xaf, 0x5c, 0x20, 0x75, 0x65, 0x03, 0xd9, 0x3a, 0xc2, 0x05, 0xbb, 0x06, 0xe9, 0x27, 0x5b, 0x24,
0x93, 0x31, 0x70, 0x29, 0xc2, 0x66, 0x69, 0xc9, 0x5a, 0xae, 0xd9, 0xc9, 0xaa, 0xf5, 0x3e, 0xd2,
0x78, 0x1a, 0xc6, 0x77, 0xb8, 0x3f, 0x82, 0x3e, 0xf7, 0x62, 0x46, 0x49, 0xf9, 0x1e, 0x8c, 0xb5,
0xfc, 0x9a, 0x8d, 0x9f, 0x6c, 0x81, 0x5c, 0x3a, 0x41, 0x72, 0xb2, 0xd1, 0x2c, 0x5a, 0x4f, 0x92,
0xfa, 0xd3, 0x30, 0xee, 0x72, 0xc5, 0xdf, 0x66, 0x1b, 0x23, 0x15, 0x97, 0x2b, 0xae, 0x77, 0x35,
0x6c, 0xfd, 0xdd, 0xba, 0x4e, 0x2a, 0xeb, 0xbe, 0x18, 0xe4, 0x22, 0x2d, 0x4d, 0x4c, 0x44, 0x9e,
0x10, 0xda, 0xf7, 0xb9, 0x03, 0xc7, 0xc2, 0x77, 0x21, 0xd6, 0x26, 0xa1, 0x5c, 0xc5, 0x87, 0xa9,
0x5c, 0xc5, 0x87, 0xec, 0x03, 0xa4, 0xa2, 0xc6, 0x91, 0xb1, 0x66, 0xe6, 0x89, 0x47, 0x2f, 0x8c,
0x40, 0x41, 0xcc, 0xc1, 0x38, 0x02, 0x5b, 0xef, 0xc0, 0x10, 0x68, 0x45, 0xb2, 0x59, 0x5e, 0x2a,
0x2f, 0x37, 0xec, 0x64, 0xd5, 0xfa, 0xd8, 0x19, 0xbd, 0x5b, 0xb1, 0x18, 0x45, 0xac, 0x47, 0x1a,
0x51, 0x8e, 0xc9, 0xa6, 0xb5, 0x54, 0x5e, 0xae, 0x3f, 0xf1, 0xd8, 0x7f, 0xd3, 0xa6, 0x8d, 0xb6,
0xcf, 0x6c, 0x6d, 0x3d, 0x4e, 0xaa, 0x6b, 0xae, 0x1b, 0x83, 0x94, 0x6c, 0x86, 0x94, 0xbc, 0x28,
0x71, 0xa6, 0xe4, 0x45, 0x18, 0xa3, 0x48, 0xc4, 0x4a, 0xfb, 0x52, 0xb6, 0xf5, 0x77, 0xeb, 0x05,
0x8b, 0x54, 0x77, 0xe4, 0x70, 0x9d, 0x4b, 0x60, 0xef, 0x27, 0x53, 0x81, 0x1c, 0x1e, 0x6a, 0x7f,
0xcd, 0x89, 0x5f, 0xbf, 0xd0, 0x82, 0x1d, 0x39, 0xd4, 0x7e, 0x56, 0x03, 0xf3, 0x81, 0x01, 0x0e,
0xe4, 0xb0, 0xd7, 0x4d, 0x24, 0x9b, 0x05, 0xbb, 0x4e, 0x6a, 0xca, 0x0b, 0x40, 0x2a, 0x1e, 0x44,
0xcd, 0xf2, 0x92, 0xb5, 0x5c, 0xb1, 0x73, 0x80, 0x5d, 0x25, 0x53, 0x52, 0x8c, 0x62, 0x07, 0x7a,
0xdd, 0x66, 0x45, 0x6f, 0xcb, 0xd6, 0xad, 0xa7, 0x48, 0x6d, 0x47, 0x0e, 0x6f, 0x01, 0x77, 0x21,
0x66, 0xef, 0x21, 0x95, 0x01, 0x97, 0xc6, 0xa2, 0xfa, 0xdb, 0x5b, 0x84, 0x1e, 0xd8, 0x9a, 0xb3,
0xf5, 0x71, 0xd2, 0xe8, 0xee, 0x6c, 0xff, 0x0f, 0x12, 0xd0, 0x74, 0x79, 0xcc, 0x63, 0x77, 0x97,
0x07, 0x69, 0x22, 0xe6, 0x40, 0xeb, 0x15, 0x8b, 0x34, 0xfa, 0xb1, 0x77, 0xe2, 0xf9, 0x30, 0x84,
0x8d, 0x53, 0xc5, 0x3e, 0x4c, 0xea, 0x62, 0x70, 0x17, 0x1c, 0x55, 0x8c, 0xdd, 0xcd, 0x0b, 0xf5,
0xec, 0x69, 0x3e, 0x1d, 0x3e, 0x22, 0xb2, 0x6f, 0xb6, 0x47, 0x68, 0x22, 0x21, 0x4a, 0x05, 0xff,
0xc7, 0x94, 0x33, 0x62, 0x32, 0x23, 0xec, 0x59, 0x71, 0x16, 0x60, 0x6d, 0x32, 0x97, 0x08, 0x0c,
0x79, 0x00, 0x87, 0x5e, 0xe8, 0xc2, 0xa9, 0x3e, 0x84, 0x4b, 0x29, 0x2f, 0xba, 0xd2, 0x43, 0xb8,
0xfd, 0xcb, 0x29, 0x52, 0xcb, 0xaa, 0x98, 0xd5, 0x49, 0x75, 0x7f, 0xe4, 0x38, 0x20, 0x25, 0x9d,
0x60, 0xf3, 0x64, 0xf6, 0x76, 0x08, 0xa7, 0x11, 0x38, 0x0a, 0x5c, 0xcd, 0x43, 0x2d, 0x36, 0x47,
0xa6, 0x3b, 0x22, 0x0c, 0xc1, 0x51, 0x9b, 0xdc, 0xf3, 0xc1, 0xa5, 0x25, 0xb6, 0x40, 0x68, 0x1f,
0xe2, 0xc0, 0x93, 0xd2, 0x13, 0x61, 0x17, 0x42, 0x0f, 0x5c, 0x5a, 0x66, 0x57, 0xc8, 0x7c, 0x47,
0xf8, 0x3e, 0x38, 0xca, 0x13, 0xe1, 0xae, 0x50, 0x1b, 0xa7, 0x9e, 0x54, 0x92, 0x56, 0x50, 0x6c,
0xcf, 0xf7, 0x61, 0xc8, 0xfd, 0xb5, 0x78, 0x38, 0x0a, 0x20, 0x54, 0xf4, 0x12, 0xca, 0x48, 0xc0,
0xae, 0x17, 0x40, 0x88, 0x92, 0x68, 0xb5, 0x80, 0x6a, 0x63, 0x31, 0x5a, 0x74, 0x8a, 0x3d, 0x44,
0x2e, 0x27, 0x68, 0x41, 0x01, 0x0f, 0x80, 0xd6, 0xd8, 0x2c, 0xa9, 0x27, 0xa4, 0x83, 0xbd, 0xfe,
0xd3, 0x94, 0x14, 0x24, 0xd8, 0xe2, 0xbe, 0x0d, 0x8e, 0x88, 0x5d, 0x5a, 0x2f, 0x98, 0x70, 0x07,
0x1c, 0x25, 0xe2, 0x5e, 0x97, 0x36, 0xd0, 0xe0, 0x04, 0xdc, 0x07, 0x1e, 0x3b, 0xc7, 0x36, 0xc8,
0x91, 0xaf, 0xe8, 0x34, 0xa3, 0xa4, 0xb1, 0xe9, 0xf9, 0xb0, 0x2b, 0xd4, 0xa6, 0x18, 0x85, 0x2e,
0x9d, 0x61, 0x33, 0x84, 0xec, 0x80, 0xe2, 0x49, 0x04, 0x66, 0x51, 0x6d, 0x87, 0x3b, 0xc7, 0x90,
0x00, 0x94, 0x2d, 0x12, 0xd6, 0xe1, 0x61, 0x28, 0x54, 0x27, 0x06, 0xae, 0x60, 0x53, 0xd7, 0x27,
0x9d, 0x43, 0x73, 0xce, 0xe0, 0x9e, 0x0f, 0x94, 0xe5, 0xdc, 0x5d, 0xf0, 0x21, 0xe3, 0x9e, 0xcf,
0xb9, 0x13, 0x1c, 0xb9, 0x17, 0xd0, 0xf8, 0xf5, 0x91, 0xe7, 0xbb, 0x3a, 0x24, 0xe6, 0x58, 0x2e,
0xa3, 0x8d, 0x89, 0xf1, 0xbb, 0xdb, 0xbd, 0xfd, 0x03, 0xba, 0xc8, 0x2e, 0x93, 0xb9, 0x04, 0xd9,
0x01, 0x15, 0x7b, 0x8e, 0x0e, 0xde, 0x15, 0x34, 0x75, 0x6f, 0xa4, 0xf6, 0x8e, 0x76, 0x20, 0x10,
0xf1, 0x98, 0x36, 0xf1, 0x40, 0xb5, 0xa4, 0xf4, 0x88, 0xe8, 0x43, 0xa8, 0x61, 0x23, 0x88, 0xd4,
0x38, 0x0f, 0x2f, 0xbd, 0xca, 0xae, 0x91, 0x2b, 0xb7, 0x23, 0x97, 0x2b, 0xe8, 0x05, 0xd8, 0x3c,
0x0e, 0xb8, 0xbc, 0x87, 0xee, 0x8e, 0x62, 0xa0, 0xd7, 0xd8, 0x55, 0xb2, 0x78, 0xf6, 0x2c, 0xb2,
0x60, 0x5d, 0xc7, 0x8d, 0xc6, 0xdb, 0x4e, 0x0c, 0x2e, 0x84, 0xca, 0xe3, 0x7e, 0xba, 0xf1, 0x46,
0x2e, 0xf5, 0x41, 0xe2, 0xc3, 0x48, 0x34, 0x9e, 0x3f, 0x48, 0xbc, 0xc9, 0x9a, 0x64, 0x61, 0x0b,
0xd4, 0x83, 0x94, 0x25, 0xa4, 0x6c, 0x7b, 0x52, 0x93, 0x6e, 0x4b, 0x88, 0x65, 0x4a, 0x79, 0x84,
0x31, 0x32, 0xb3, 0x05, 0x0a, 0xc1, 0x14, 0x6b, 0x61, 0x9c, 0x8c, 0x79, 0xb6, 0xf0, 0x21, 0x85,
0xff, 0x0f, 0x63, 0xd0, 0x8d, 0x45, 0x54, 0x04, 0x1f, 0x45, 0x37, 0xf7, 0x22, 0x88, 0xb9, 0x02,
0x94, 0x51, 0xa4, 0x3d, 0x86, 0x72, 0xf6, 0x01, 0x23, 0x50, 0x84, 0xff, 0x3f, 0x87, 0x8b, 0x5a,
0xdf, 0x81, 0x39, 0x9c, 0x70, 0x83, 0xe9, 0x7c, 0x29, 0x69, 0x19, 0xbd, 0x4e, 0x94, 0x64, 0x15,
0x9d, 0x12, 0xdf, 0x89, 0xa9, 0x62, 0xf6, 0x6d, 0xc5, 0x3c, 0x54, 0x29, 0xde, 0x66, 0x8f, 0x90,
0x1b, 0x36, 0x1c, 0xc5, 0x20, 0x8f, 0xfb, 0xc2, 0xf7, 0x9c, 0x71, 0x2f, 0x3c, 0x12, 0x59, 0x4a,
0x22, 0xcb, 0xbb, 0xd0, 0x12, 0x0c, 0x8b, 0xa1, 0xa7, 0xf0, 0xbb, 0x31, 0x26, 0xbb, 0x42, 0xed,
0x63, 0x83, 0xdb, 0xd6, 0x2d, 0x93, 0x3e, 0x8e, 0x5a, 0x76, 0x85, 0x0d, 0x91, 0xef, 0x39, 0x7c,
0xed, 0x84, 0x7b, 0x3e, 0x1f, 0xf8, 0x40, 0x57, 0x30, 0x28, 0xfb, 0x30, 0xc4, 0x92, 0xcd, 0xce,
0x77, 0x95, 0x31, 0x32, 0xdd, 0xed, 0xda, 0xf0, 0x89, 0x11, 0x48, 0x65, 0x73, 0x07, 0xe8, 0x9f,
0xab, 0xed, 0x67, 0x09, 0xd1, 0x49, 0x85, 0x17, 0x0a, 0x40, 0x15, 0xf9, 0x6a, 0x57, 0x84, 0x40,
0x27, 0x58, 0x83, 0x4c, 0xdd, 0x0e, 0x3d, 0x29, 0x47, 0xe0, 0x52, 0x0b, 0x0b, 0xaa, 0x17, 0xf6,
0x63, 0x31, 0xc4, 0xd9, 0x45, 0x4b, 0x48, 0xdd, 0xf4, 0x42, 0x4f, 0x1e, 0xeb, 0x56, 0x42, 0xc8,
0x64, 0x52, 0x59, 0x95, 0xf6, 0xf3, 0x16, 0x69, 0x24, 0x36, 0x18, 0xe1, 0x0b, 0x84, 0x16, 0xd7,
0xb9, 0xf8, 0x2c, 0xa1, 0x2d, 0x6c, 0x6b, 0x5b, 0xb1, 0xb8, 0xef, 0x85, 0x43, 0x5a, 0x42, 0x69,
0xfb, 0xc0, 0x7d, 0x2d, 0xb9, 0x4e, 0xaa, 0x9b, 0xfe, 0x48, 0xab, 0xa9, 0x68, 0xa5, 0xb8, 0x40,
0xb6, 0x4b, 0x48, 0xc2, 0x04, 0x88, 0xc0, 0xa5, 0x93, 0x6c, 0x9a, 0xd4, 0x4c, 0xda, 0x23, 0xad,
0xda, 0xfe, 0x10, 0x99, 0x3d, 0x37, 0xf7, 0xd9, 0x14, 0xa9, 0x24, 0xaa, 0x29, 0x69, 0xac, 0x7b,
0x21, 0x8f, 0xc7, 0xa6, 0xb7, 0x50, 0x17, 0x6b, 0x6e, 0xd3, 0x17, 0x5c, 0x25, 0x00, 0xb4, 0x5f,
0x6c, 0xe8, 0xc1, 0xab, 0x37, 0x4e, 0x93, 0xda, 0xed, 0xd0, 0x85, 0x23, 0x2f, 0x04, 0x97, 0x4e,
0xe8, 0x9a, 0x37, 0xd5, 0x92, 0x17, 0x9f, 0x8b, 0x11, 0x44, 0x63, 0x0a, 0x18, 0x60, 0xe1, 0xde,
0xe2, 0xb2, 0x00, 0x1d, 0xe1, 0xb9, 0x75, 0xf5, 0xb5, 0x6e, 0x50, 0xdc, 0x3e, 0xd4, 0xe7, 0x76,
0x2c, 0xee, 0xe7, 0x98, 0xa4, 0xc7, 0xa8, 0x69, 0x0b, 0xd4, 0xfe, 0x58, 0x2a, 0x08, 0x3a, 0x22,
0x3c, 0xf2, 0x86, 0x92, 0x7a, 0xa8, 0x69, 0x5b, 0x70, 0xb7, 0xb0, 0xfd, 0x2e, 0x66, 0x8e, 0x0d,
0x3e, 0x70, 0x59, 0x94, 0x7a, 0x4f, 0x77, 0x3d, 0x6d, 0xea, 0x9a, 0xef, 0x71, 0x49, 0x7d, 0x74,
0x05, 0xad, 0x34, 0xcb, 0x00, 0x0f, 0x75, 0xcd, 0x57, 0x10, 0x9b, 0x75, 0xc8, 0x16, 0xc8, 0xac,
0xe1, 0xef, 0xf3, 0x58, 0x79, 0x5a, 0xc8, 0x4b, 0x96, 0x4e, 0x9f, 0x58, 0x44, 0x39, 0xf6, 0x32,
0x0e, 0x99, 0xc6, 0x2d, 0x2e, 0x73, 0xe8, 0xa7, 0x16, 0x5b, 0x24, 0x73, 0xa9, 0x6b, 0x39, 0xfe,
0x33, 0x8b, 0xcd, 0x93, 0x19, 0x74, 0x2d, 0xc3, 0x24, 0xfd, 0xb9, 0x06, 0xd1, 0x89, 0x02, 0xf8,
0x8a, 0x96, 0x90, 0x78, 0x51, 0xc0, 0x7f, 0xa1, 0x95, 0xa1, 0x84, 0x24, 0x89, 0x24, 0x7d, 0xd5,
0x42, 0x4b, 0x53, 0x65, 0x09, 0x4c, 0x5f, 0xd3, 0x8c, 0x28, 0x35, 0x63, 0x7c, 0x5d, 0x33, 0x26,
0x32, 0x33, 0xf4, 0x0d, 0x8d, 0xde, 0xe2, 0xa1, 0x2b, 0x8e, 0x8e, 0x32, 0xf4, 0x4d, 0x8b, 0x35,
0xc9, 0x3c, 0x6e, 0x5f, 0xe7, 0x3e, 0x0f, 0x9d, 0x9c, 0xff, 0x2d, 0x8b, 0x5d, 0x26, 0xf4, 0x9c,
0x3a, 0x49, 0x9f, 0x2b, 0x31, 0x9a, 0xc6, 0x57, 0x17, 0x0f, 0xfd, 0x62, 0x49, 0xc7, 0x2a, 0x61,
0x34, 0xd8, 0x97, 0x4a, 0x6c, 0xc6, 0x04, 0xdd, 0xac, 0xbf, 0x5c, 0x62, 0x75, 0x32, 0xd9, 0x0b,
0x25, 0xc4, 0x8a, 0x7e, 0x16, 0xf3, 0x7b, 0xd2, 0x74, 0x50, 0xfa, 0x39, 0x2c, 0xa3, 0x4b, 0x3a,
0xbf, 0xe9, 0x0b, 0x38, 0x9d, 0x99, 0x0d, 0x12, 0x42, 0xb7, 0x50, 0x3b, 0x92, 0x7e, 0x5e, 0xef,
0x30, 0xe3, 0x8f, 0xfe, 0xb5, 0xac, 0x43, 0x53, 0x9c, 0x85, 0x7f, 0x2b, 0xa3, 0x09, 0x5b, 0xa0,
0xf2, 0x72, 0xa6, 0x7f, 0x2f, 0xb3, 0xab, 0xe4, 0x72, 0x8a, 0xe9, 0xc9, 0x94, 0x15, 0xf2, 0x3f,
0xca, 0xec, 0x3a, 0xb9, 0x82, 0x6d, 0x3a, 0xcb, 0x1b, 0xdc, 0xe4, 0x49, 0xe5, 0x39, 0x92, 0xfe,
0xb3, 0xcc, 0xae, 0x91, 0xc5, 0x2d, 0x50, 0xd9, 0x79, 0x14, 0x88, 0xff, 0x2a, 0xb3, 0x69, 0x32,
0x65, 0xe3, 0xe8, 0x82, 0x13, 0xa0, 0xaf, 0x96, 0xf1, 0x50, 0xd3, 0x65, 0x62, 0xce, 0x6b, 0x65,
0x0c, 0xf5, 0x33, 0x5c, 0x39, 0xc7, 0xdd, 0xa0, 0x73, 0xcc, 0xc3, 0x10, 0x7c, 0x49, 0x5f, 0x2f,
0x63, 0x40, 0x6d, 0x08, 0xc4, 0x09, 0x14, 0xe0, 0x37, 0xb4, 0xd3, 0x9a, 0xf9, 0x23, 0x23, 0x88,
0xc7, 0x19, 0xe1, 0xcd, 0x32, 0x1e, 0x8d, 0xe1, 0x3f, 0x4b, 0x79, 0xab, 0xcc, 0x6e, 0x90, 0xa6,
0x69, 0x16, 0xe9, 0xc1, 0x20, 0x71, 0x08, 0xd8, 0x5e, 0xe9, 0x73, 0x95, 0x4c, 0x62, 0x17, 0x7c,
0xc5, 0xb3, 0x7d, 0x9f, 0xaa, 0xa0, 0x5d, 0x58, 0x5c, 0x79, 0x57, 0x95, 0xf4, 0xf9, 0x0a, 0x9e,
0xe8, 0x16, 0xa8, 0xa4, 0xb1, 0x4a, 0xfa, 0x69, 0x8d, 0x24, 0x92, 0xb5, 0xc8, 0x5f, 0x55, 0xd8,
0x2c, 0x21, 0xa6, 0x26, 0x35, 0xf0, 0xeb, 0x54, 0x14, 0xde, 0x5d, 0x4e, 0x20, 0xd6, 0x8d, 0x9d,
0xfe, 0x26, 0x53, 0x50, 0xe8, 0x7c, 0xf4, 0xb7, 0x15, 0x0c, 0xd9, 0x81, 0x17, 0xc0, 0x81, 0xe7,
0xdc, 0xa3, 0x5f, 0xad, 0x61, 0xc8, 0xb4, 0x47, 0xbb, 0xc2, 0x05, 0x73, 0xc2, 0x5f, 0xab, 0x61,
0xc2, 0x60, 0x1e, 0x9a, 0x84, 0xf9, 0xba, 0x5e, 0x27, 0xdd, 0xbb, 0xd7, 0xa5, 0xdf, 0xc0, 0x3b,
0x14, 0x49, 0xd6, 0x07, 0xfb, 0x7b, 0xf4, 0x9b, 0x35, 0x54, 0xb5, 0xe6, 0xfb, 0xc2, 0xe1, 0x2a,
0xab, 0x86, 0x6f, 0xd5, 0xb0, 0x9c, 0x0a, 0xda, 0x93, 0x53, 0x7b, 0xb1, 0x86, 0xb1, 0x4f, 0x70,
0x9d, 0x6c, 0x5d, 0x6c, 0x8a, 0xdf, 0xd6, 0x52, 0xf1, 0x05, 0x87, 0x96, 0x1c, 0x28, 0xfa, 0x1d,
0xcd, 0x77, 0xfe, 0x5a, 0x40, 0x7f, 0x57, 0x4f, 0xf2, 0xab, 0x80, 0xfd, 0xbe, 0x6e, 0xea, 0xe3,
0xec, 0x3d, 0x80, 0xfe, 0x41, 0xc3, 0xe7, 0xef, 0x0e, 0xf4, 0x8f, 0x75, 0x34, 0xac, 0x38, 0xfe,
0xf1, 0x0a, 0x2c, 0xe9, 0x9f, 0xea, 0x68, 0x41, 0x3e, 0xe8, 0xe9, 0x77, 0x1b, 0x18, 0xac, 0x74,
0xc4, 0xd3, 0xef, 0x35, 0xd0, 0xcd, 0x73, 0xc3, 0x9d, 0x7e, 0xbf, 0xa1, 0x8f, 0x23, 0x1b, 0xeb,
0xf4, 0x07, 0x05, 0x00, 0xb9, 0xe8, 0x0f, 0x1b, 0xba, 0x03, 0x9d, 0x19, 0xe5, 0xf4, 0x47, 0x0d,
0xb4, 0xed, 0xfc, 0x10, 0xa7, 0x3f, 0x6e, 0x98, 0xe3, 0xce, 0xc6, 0x37, 0xfd, 0x49, 0x03, 0x2b,
0xe0, 0xe2, 0xc1, 0x4d, 0x5f, 0xd2, 0xba, 0xf2, 0x91, 0x4d, 0x5f, 0x6e, 0xb4, 0x5b, 0xa4, 0xda,
0x95, 0xbe, 0x9e, 0x1b, 0x55, 0x52, 0xee, 0x4a, 0x9f, 0x4e, 0x60, 0x9b, 0x5d, 0x17, 0xc2, 0xdf,
0x38, 0x8d, 0xe2, 0x3b, 0xef, 0xa5, 0x56, 0x7b, 0x9d, 0xcc, 0x76, 0x44, 0x10, 0xf1, 0xac, 0xdc,
0xf4, 0xa8, 0x30, 0x33, 0x06, 0x5c, 0x93, 0x2a, 0x13, 0xd8, 0xab, 0x37, 0x4e, 0xc1, 0x19, 0xe9,
0x89, 0x66, 0xe1, 0x12, 0x37, 0x61, 0x90, 0x5d, 0x5a, 0x6a, 0x3f, 0x4b, 0x68, 0x47, 0x84, 0xd2,
0x93, 0x0a, 0x42, 0x67, 0xbc, 0x0d, 0x27, 0xe0, 0xeb, 0xb9, 0xa9, 0x62, 0x11, 0x0e, 0xe9, 0x84,
0x7e, 0x27, 0x80, 0xbe, 0xef, 0x9b, 0xe9, 0xba, 0x8e, 0x77, 0x01, 0xfd, 0x18, 0x98, 0x21, 0x64,
0xe3, 0x04, 0x42, 0x35, 0xe2, 0xbe, 0x3f, 0xa6, 0x65, 0x5c, 0x77, 0x46, 0x52, 0x89, 0xc0, 0xfb,
0xa4, 0x9e, 0xdf, 0x5f, 0xb1, 0x48, 0xdd, 0x8c, 0xd2, 0xcc, 0x34, 0xb3, 0xec, 0x43, 0xe8, 0x7a,
0x5a, 0x38, 0xde, 0x65, 0x35, 0x94, 0x0c, 0x7d, 0x2b, 0x67, 0xda, 0x57, 0x3c, 0x56, 0xe9, 0xa3,
0xc3, 0x40, 0x5d, 0x71, 0x3f, 0xf4, 0x05, 0x77, 0xf5, 0x3c, 0xcf, 0xb6, 0xf6, 0x79, 0x2c, 0xf5,
0x50, 0xc7, 0xab, 0x7e, 0x22, 0x3f, 0xd6, 0xfe, 0xb8, 0xf4, 0x52, 0x0e, 0xe6, 0x3e, 0x4f, 0xe2,
0xf0, 0x34, 0xa0, 0x4e, 0xf6, 0x34, 0xd3, 0x49, 0x7b, 0x99, 0x90, 0xfc, 0xe1, 0xa6, 0xfd, 0xc9,
0x87, 0xe0, 0x04, 0x46, 0x65, 0xcb, 0x17, 0x03, 0xee, 0x53, 0xab, 0xfd, 0x99, 0x12, 0x99, 0x3d,
0xf7, 0x38, 0x43, 0x8b, 0xb2, 0xc5, 0x9a, 0x8f, 0xe7, 0x75, 0x83, 0x3c, 0x94, 0x21, 0x0f, 0x8c,
0x7a, 0x0b, 0xaf, 0x7f, 0x19, 0xf9, 0xdc, 0xcc, 0x2f, 0xb1, 0x9b, 0xe4, 0x5a, 0x4e, 0x7c, 0x70,
0xd2, 0x63, 0xbb, 0x6d, 0x66, 0x0c, 0xe7, 0x47, 0x7e, 0x05, 0xe3, 0x98, 0x51, 0xb1, 0x07, 0x98,
0x87, 0x57, 0xfe, 0x92, 0x34, 0xa3, 0x8c, 0x4e, 0xe2, 0x5b, 0x28, 0xb7, 0x31, 0x4b, 0x26, 0x5a,
0xc5, 0xc8, 0x65, 0x84, 0x64, 0xcc, 0x4c, 0x9d, 0x01, 0x93, 0x71, 0x53, 0xfb, 0xa0, 0x20, 0x73,
0xd9, 0x73, 0xf6, 0x10, 0x4e, 0xd5, 0xa1, 0x18, 0xdc, 0x65, 0x37, 0x57, 0xcc, 0x6f, 0xa8, 0x95,
0xf4, 0x37, 0xd4, 0xca, 0x0e, 0x48, 0xc9, 0x87, 0xb0, 0x17, 0x69, 0x1b, 0x9b, 0x7f, 0xa9, 0xea,
0x77, 0xfa, 0x23, 0x17, 0xff, 0xfd, 0x28, 0xbc, 0xbb, 0xed, 0xd9, 0xa8, 0xb0, 0xda, 0x1b, 0xdc,
0x5d, 0x7f, 0x86, 0xcc, 0x78, 0x22, 0xdd, 0x37, 0x8c, 0x23, 0x67, 0xbd, 0xde, 0xd1, 0xfb, 0xfa,
0x28, 0xa3, 0x6f, 0x7d, 0xf4, 0xc9, 0xa1, 0xa7, 0x8e, 0x47, 0x03, 0x94, 0xb6, 0x6a, 0xd8, 0x1e,
0xf7, 0x44, 0xf2, 0xb5, 0xea, 0x85, 0x0a, 0x7b, 0x85, 0x6f, 0x7e, 0x90, 0xad, 0x1a, 0x8d, 0xd1,
0xe0, 0x0b, 0x96, 0x35, 0x98, 0xd4, 0xd0, 0x93, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x59,
0x0b, 0xcb, 0x66, 0x13, 0x00, 0x00,
}

View File

@ -310,6 +310,7 @@ message ListPolicyResponse {
// Contain error_code and reason
common.Status status = 1;
repeated string policy_infos = 2;
repeated string user_roles = 3;
}
message ShowConfigurationsRequest {

View File

@ -2539,6 +2539,7 @@ type ListPolicyResponse struct {
// Contain error_code and reason
Status *commonpb.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
PolicyInfos []string `protobuf:"bytes,2,rep,name=policy_infos,json=policyInfos,proto3" json:"policy_infos,omitempty"`
UserRoles []string `protobuf:"bytes,3,rep,name=user_roles,json=userRoles,proto3" json:"user_roles,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -2583,6 +2584,13 @@ func (m *ListPolicyResponse) GetPolicyInfos() []string {
return nil
}
func (m *ListPolicyResponse) GetUserRoles() []string {
if m != nil {
return m.UserRoles
}
return nil
}
type ShowConfigurationsRequest struct {
Base *commonpb.MsgBase `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
Pattern string `protobuf:"bytes,2,opt,name=pattern,proto3" json:"pattern,omitempty"`
@ -2722,142 +2730,144 @@ func init() {
func init() { proto.RegisterFile("internal.proto", fileDescriptor_41f4a519b878ee3b) }
var fileDescriptor_41f4a519b878ee3b = []byte{
// 2192 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x59, 0xcd, 0x73, 0x1b, 0x49,
0x15, 0xdf, 0xd1, 0xc8, 0x96, 0xf4, 0x24, 0xdb, 0x72, 0xc7, 0xd9, 0x55, 0x9c, 0xec, 0xae, 0x33,
0x2c, 0x60, 0x12, 0x36, 0x09, 0xde, 0xdd, 0x64, 0x0b, 0x28, 0x42, 0x62, 0x2d, 0xc1, 0x95, 0x0f,
0xcc, 0x38, 0xa4, 0x0a, 0x2e, 0x53, 0x2d, 0x4d, 0x5b, 0x6a, 0x32, 0x33, 0x3d, 0xe9, 0xee, 0xb1,
0xa3, 0x9c, 0x38, 0x70, 0x82, 0x82, 0x1b, 0x97, 0xad, 0x82, 0x33, 0x17, 0xce, 0x7b, 0x83, 0x2a,
0x4e, 0x9c, 0x38, 0x71, 0xe1, 0x5f, 0xa1, 0x38, 0x50, 0xfd, 0x31, 0xa3, 0x91, 0x2c, 0x3b, 0xb2,
0x53, 0xbb, 0x1b, 0xaa, 0xf6, 0x36, 0xfd, 0xde, 0xeb, 0xee, 0xd7, 0xef, 0xfd, 0xde, 0xeb, 0xf7,
0x7a, 0x60, 0x99, 0x26, 0x92, 0xf0, 0x04, 0x47, 0xd7, 0x52, 0xce, 0x24, 0x43, 0xe7, 0x63, 0x1a,
0x1d, 0x64, 0xc2, 0x8c, 0xae, 0xe5, 0xcc, 0xf5, 0x56, 0x9f, 0xc5, 0x31, 0x4b, 0x0c, 0x79, 0xbd,
0x25, 0xfa, 0x43, 0x12, 0x63, 0x33, 0xf2, 0xfe, 0xea, 0xc0, 0xd2, 0x36, 0x8b, 0x53, 0x96, 0x90,
0x44, 0xee, 0x24, 0xfb, 0x0c, 0xbd, 0x09, 0x8b, 0x09, 0x0b, 0xc9, 0x4e, 0xb7, 0xe3, 0x6c, 0x38,
0x9b, 0xae, 0x6f, 0x47, 0x08, 0x41, 0x95, 0xb3, 0x88, 0x74, 0x2a, 0x1b, 0xce, 0x66, 0xc3, 0xd7,
0xdf, 0xe8, 0x36, 0x80, 0x90, 0x58, 0x92, 0xa0, 0xcf, 0x42, 0xd2, 0x71, 0x37, 0x9c, 0xcd, 0xe5,
0xad, 0x8d, 0x6b, 0x33, 0xb5, 0xb8, 0xb6, 0xa7, 0x04, 0xb7, 0x59, 0x48, 0xfc, 0x86, 0xc8, 0x3f,
0xd1, 0x0f, 0x01, 0xc8, 0x73, 0xc9, 0x71, 0x40, 0x93, 0x7d, 0xd6, 0xa9, 0x6e, 0xb8, 0x9b, 0xcd,
0xad, 0xcb, 0x93, 0x0b, 0x58, 0xe5, 0xef, 0x93, 0xd1, 0x13, 0x1c, 0x65, 0x64, 0x17, 0x53, 0xee,
0x37, 0xf4, 0x24, 0xa5, 0xae, 0xf7, 0x6f, 0x07, 0x56, 0x8a, 0x03, 0xe8, 0x3d, 0x04, 0xfa, 0x2e,
0x2c, 0xe8, 0x2d, 0xf4, 0x09, 0x9a, 0x5b, 0xef, 0x1d, 0xa3, 0xd1, 0xc4, 0xb9, 0x7d, 0x33, 0x05,
0xfd, 0x0c, 0xce, 0x89, 0xac, 0xd7, 0xcf, 0x59, 0x81, 0xa6, 0x8a, 0x4e, 0x45, 0xab, 0x36, 0xdf,
0x4a, 0xa8, 0xbc, 0x80, 0x55, 0xe9, 0x03, 0x58, 0x54, 0x2b, 0x65, 0x42, 0x5b, 0xa9, 0xb9, 0x75,
0x71, 0xe6, 0x21, 0xf7, 0xb4, 0x88, 0x6f, 0x45, 0xbd, 0x8b, 0x70, 0xe1, 0x1e, 0x91, 0x53, 0xa7,
0xf3, 0xc9, 0xb3, 0x8c, 0x08, 0x69, 0x99, 0x8f, 0x69, 0x4c, 0x1e, 0xd3, 0xfe, 0xd3, 0xed, 0x21,
0x4e, 0x12, 0x12, 0xe5, 0xcc, 0xb7, 0xe1, 0xe2, 0x3d, 0xa2, 0x27, 0x50, 0x21, 0x69, 0x5f, 0x4c,
0xb1, 0xcf, 0xc3, 0xb9, 0x7b, 0x44, 0x76, 0xc3, 0x29, 0xf2, 0x13, 0xa8, 0x3f, 0x52, 0xce, 0x56,
0x30, 0xb8, 0x09, 0x35, 0x1c, 0x86, 0x9c, 0x08, 0x61, 0xad, 0x78, 0x69, 0xa6, 0xc6, 0x77, 0x8c,
0x8c, 0x9f, 0x0b, 0xcf, 0x82, 0x89, 0xf7, 0x4b, 0x80, 0x9d, 0x84, 0xca, 0x5d, 0xcc, 0x71, 0x2c,
0x8e, 0x05, 0x58, 0x17, 0x5a, 0x42, 0x62, 0x2e, 0x83, 0x54, 0xcb, 0x59, 0x93, 0xcf, 0x81, 0x86,
0xa6, 0x9e, 0x66, 0x56, 0xf7, 0x7e, 0x0e, 0xb0, 0x27, 0x39, 0x4d, 0x06, 0x0f, 0xa8, 0x90, 0x6a,
0xaf, 0x03, 0x25, 0xa7, 0x0e, 0xe1, 0x6e, 0x36, 0x7c, 0x3b, 0x2a, 0xb9, 0xa3, 0x32, 0xbf, 0x3b,
0x6e, 0x43, 0x33, 0x37, 0xf7, 0x43, 0x31, 0x40, 0x37, 0xa0, 0xda, 0xc3, 0x82, 0x9c, 0x68, 0x9e,
0x87, 0x62, 0x70, 0x17, 0x0b, 0xe2, 0x6b, 0x49, 0xef, 0x2f, 0x15, 0x58, 0x9b, 0x70, 0x8b, 0x35,
0xfc, 0xe9, 0x97, 0x52, 0x66, 0x0e, 0x7b, 0x3b, 0x5d, 0xad, 0xbe, 0xeb, 0xeb, 0x6f, 0xe4, 0x41,
0xab, 0xcf, 0xa2, 0x88, 0xf4, 0x25, 0x65, 0xc9, 0x4e, 0x57, 0x23, 0xcd, 0xf5, 0x27, 0x68, 0x4a,
0x26, 0xc5, 0x5c, 0x52, 0x33, 0x14, 0x3a, 0xe4, 0x5c, 0x7f, 0x82, 0x86, 0xbe, 0x05, 0x6d, 0xc9,
0xf1, 0x01, 0x89, 0x02, 0x49, 0x63, 0x22, 0x24, 0x8e, 0xd3, 0xce, 0xc2, 0x86, 0xb3, 0x59, 0xf5,
0x57, 0x0c, 0xfd, 0x71, 0x4e, 0x46, 0xd7, 0xe1, 0xdc, 0x20, 0xc3, 0x1c, 0x27, 0x92, 0x90, 0x92,
0xf4, 0xa2, 0x96, 0x46, 0x05, 0x6b, 0x3c, 0xe1, 0x2a, 0xac, 0x2a, 0x31, 0x96, 0xc9, 0x92, 0x78,
0x4d, 0x8b, 0xb7, 0x2d, 0xa3, 0x10, 0xf6, 0x3e, 0x73, 0xe0, 0xfc, 0x94, 0xbd, 0x44, 0xca, 0x12,
0x41, 0xce, 0x60, 0xb0, 0xb3, 0x78, 0x1c, 0xdd, 0x32, 0x89, 0x44, 0x05, 0xed, 0x9c, 0x58, 0x34,
0xf2, 0xde, 0x6f, 0x5c, 0x78, 0x6b, 0x9b, 0x13, 0x9d, 0xe6, 0x72, 0xeb, 0x9f, 0xdd, 0xd9, 0x6f,
0x41, 0x2d, 0xec, 0x05, 0x09, 0x8e, 0xf3, 0xb0, 0x5a, 0x0c, 0x7b, 0x8f, 0x70, 0x4c, 0xd0, 0x37,
0x60, 0x79, 0xec, 0x5d, 0x45, 0xd1, 0x3e, 0x6f, 0xf8, 0x53, 0x54, 0xf4, 0x1e, 0x2c, 0x15, 0x1e,
0xd6, 0x62, 0x55, 0x2d, 0x36, 0x49, 0x2c, 0x30, 0xb5, 0x70, 0x02, 0xa6, 0x16, 0x67, 0x60, 0x6a,
0x03, 0x9a, 0x25, 0xfc, 0x68, 0x6f, 0xba, 0x7e, 0x99, 0xa4, 0xc2, 0xd0, 0xdc, 0x3a, 0x9d, 0xfa,
0x86, 0xb3, 0xd9, 0xf2, 0xed, 0x08, 0xdd, 0x80, 0x73, 0x07, 0x94, 0xcb, 0x0c, 0x47, 0x36, 0x13,
0x29, 0x3d, 0x44, 0xa7, 0xa1, 0x63, 0x75, 0x16, 0x0b, 0x6d, 0xc1, 0x5a, 0x3a, 0x1c, 0x09, 0xda,
0x9f, 0x9a, 0x02, 0x7a, 0xca, 0x4c, 0x9e, 0xf7, 0x77, 0x07, 0xce, 0x77, 0x39, 0x4b, 0x5f, 0x0b,
0x57, 0xe4, 0x46, 0xae, 0x9e, 0x60, 0xe4, 0x85, 0xa3, 0x46, 0xf6, 0x7e, 0x57, 0x81, 0x37, 0x0d,
0xa2, 0x76, 0x73, 0xc3, 0x7e, 0x0e, 0xa7, 0xf8, 0x26, 0xac, 0x8c, 0x77, 0x35, 0x02, 0xb3, 0x8f,
0xf1, 0x75, 0x58, 0x2e, 0x1c, 0x6c, 0xe4, 0xbe, 0x58, 0x48, 0x79, 0xbf, 0xad, 0xc0, 0x9a, 0x72,
0xea, 0x57, 0xd6, 0x50, 0xd6, 0xf8, 0x93, 0x03, 0xc8, 0xa0, 0xe3, 0x4e, 0x44, 0xb1, 0xf8, 0x32,
0x6d, 0xb1, 0x06, 0x0b, 0x58, 0xe9, 0x60, 0x4d, 0x60, 0x06, 0x9e, 0x80, 0xb6, 0xf2, 0xd6, 0xe7,
0xa5, 0x5d, 0xb1, 0xa9, 0x5b, 0xde, 0xf4, 0x8f, 0x0e, 0xac, 0xde, 0x89, 0x24, 0xe1, 0xaf, 0xa9,
0x51, 0xfe, 0x56, 0xc9, 0xbd, 0xb6, 0x93, 0x84, 0xe4, 0xf9, 0x97, 0xa9, 0xe0, 0xdb, 0x00, 0xfb,
0x94, 0x44, 0x61, 0x19, 0xbd, 0x0d, 0x4d, 0x79, 0x25, 0xe4, 0x76, 0xa0, 0xa6, 0x17, 0x29, 0x50,
0x9b, 0x0f, 0x55, 0xb5, 0x67, 0x2a, 0x7f, 0x5b, 0xed, 0xd5, 0xe7, 0xae, 0xf6, 0xf4, 0x34, 0x5b,
0xed, 0xfd, 0xb3, 0x0a, 0x4b, 0x3b, 0x89, 0x20, 0x5c, 0x9e, 0xdd, 0x78, 0x97, 0xa0, 0x21, 0x86,
0x98, 0xeb, 0x83, 0x5a, 0xf3, 0x8d, 0x09, 0x65, 0xd3, 0xba, 0x2f, 0x33, 0x6d, 0x75, 0xce, 0xe4,
0xb0, 0x70, 0x52, 0x72, 0x58, 0x3c, 0xc1, 0xc4, 0xb5, 0x97, 0x27, 0x87, 0xfa, 0xd1, 0xdb, 0x57,
0x1d, 0x90, 0x0c, 0x62, 0xd5, 0x9e, 0x74, 0x3b, 0x0d, 0xcd, 0x1f, 0x13, 0xd0, 0x3b, 0x00, 0x45,
0x25, 0x66, 0xee, 0xd1, 0xaa, 0x5f, 0xa2, 0xa8, 0xbb, 0x9b, 0xb3, 0x43, 0x55, 0x2b, 0x36, 0x75,
0xad, 0x68, 0x47, 0xe8, 0x43, 0xa8, 0x73, 0x76, 0x18, 0x84, 0x58, 0xe2, 0x4e, 0x4b, 0x3b, 0xef,
0xc2, 0x4c, 0x63, 0xdf, 0x8d, 0x58, 0xcf, 0xaf, 0x71, 0x76, 0xd8, 0xc5, 0x12, 0xa3, 0xdb, 0xd0,
0xd4, 0x08, 0x10, 0x66, 0xe2, 0x92, 0x9e, 0xf8, 0xce, 0xe4, 0x44, 0xdb, 0xa0, 0xfe, 0x48, 0xc9,
0xa9, 0x49, 0xbe, 0x81, 0xa6, 0xd0, 0x0b, 0x5c, 0x80, 0x7a, 0x92, 0xc5, 0x01, 0x67, 0x87, 0xa2,
0xb3, 0xac, 0xeb, 0xc6, 0x5a, 0x92, 0xc5, 0x3e, 0x3b, 0x14, 0xe8, 0x2e, 0xd4, 0x0e, 0x08, 0x17,
0x94, 0x25, 0x9d, 0x15, 0xdd, 0x8a, 0x6e, 0x1e, 0xd3, 0xae, 0x19, 0xc4, 0xa8, 0xe5, 0x9e, 0x18,
0x79, 0x3f, 0x9f, 0xe8, 0xfd, 0xab, 0x0a, 0x4b, 0x7b, 0x04, 0xf3, 0xfe, 0xf0, 0xec, 0x80, 0x5a,
0x83, 0x05, 0x4e, 0x9e, 0x15, 0xc5, 0xb9, 0x19, 0x14, 0xfe, 0x75, 0x4f, 0xf0, 0x6f, 0x75, 0x8e,
0x8a, 0x7d, 0x61, 0x46, 0xc5, 0xde, 0x06, 0x37, 0x14, 0x91, 0x86, 0x4e, 0xc3, 0x57, 0x9f, 0xaa,
0xce, 0x4e, 0x23, 0xdc, 0x27, 0x43, 0x16, 0x85, 0x84, 0x07, 0x03, 0xce, 0x32, 0x53, 0x67, 0xb7,
0xfc, 0x76, 0x89, 0x71, 0x4f, 0xd1, 0xd1, 0x2d, 0xa8, 0x87, 0x22, 0x0a, 0xe4, 0x28, 0x25, 0x1a,
0x3f, 0xcb, 0xc7, 0x1c, 0xb3, 0x2b, 0xa2, 0xc7, 0xa3, 0x94, 0xf8, 0xb5, 0xd0, 0x7c, 0xa0, 0x1b,
0xb0, 0x26, 0x08, 0xa7, 0x38, 0xa2, 0x2f, 0x48, 0x18, 0x90, 0xe7, 0x29, 0x0f, 0xd2, 0x08, 0x27,
0x1a, 0x64, 0x2d, 0x1f, 0x8d, 0x79, 0x9f, 0x3c, 0x4f, 0xf9, 0x6e, 0x84, 0x13, 0xb4, 0x09, 0x6d,
0x96, 0xc9, 0x34, 0x93, 0x81, 0x85, 0x01, 0x0d, 0x35, 0xe6, 0x5c, 0x7f, 0xd9, 0xd0, 0xb5, 0xd7,
0xc5, 0x4e, 0x38, 0xb3, 0x0b, 0x69, 0x9e, 0xaa, 0x0b, 0x69, 0x9d, 0xae, 0x0b, 0x59, 0x9a, 0xdd,
0x85, 0xa0, 0x65, 0xa8, 0x24, 0xcf, 0x34, 0xd6, 0x5c, 0xbf, 0x92, 0x3c, 0x53, 0x8e, 0x94, 0x2c,
0x7d, 0xaa, 0x31, 0xe6, 0xfa, 0xfa, 0x5b, 0x05, 0x51, 0x4c, 0x24, 0xa7, 0x7d, 0x65, 0x96, 0x4e,
0x5b, 0xfb, 0xa1, 0x44, 0xf1, 0xfe, 0xeb, 0x8e, 0x61, 0x25, 0xb2, 0x48, 0x8a, 0x2f, 0xaa, 0x83,
0x29, 0xb0, 0xe8, 0x96, 0xb1, 0xf8, 0x2e, 0x34, 0x8d, 0x72, 0xc6, 0xe7, 0xd5, 0x69, 0x7d, 0x95,
0x80, 0x8a, 0xb2, 0x67, 0x19, 0xe1, 0x94, 0x08, 0x9b, 0xf6, 0x21, 0xc9, 0xe2, 0x9f, 0x1a, 0x0a,
0x3a, 0x07, 0x0b, 0x92, 0xa5, 0xc1, 0xd3, 0x3c, 0x5d, 0x49, 0x96, 0xde, 0x47, 0xdf, 0x87, 0x75,
0x41, 0x70, 0x44, 0xc2, 0xa0, 0x48, 0x2f, 0x22, 0x10, 0xfa, 0xd8, 0x24, 0xec, 0xd4, 0xb4, 0x9b,
0x3b, 0x46, 0x62, 0xaf, 0x10, 0xd8, 0xb3, 0x7c, 0xe5, 0xc5, 0xbe, 0x29, 0xdb, 0x27, 0xa6, 0xd5,
0x75, 0x65, 0x8f, 0xc6, 0xac, 0x62, 0xc2, 0xc7, 0xd0, 0x19, 0x44, 0xac, 0x87, 0xa3, 0xe0, 0xc8,
0xae, 0xba, 0x85, 0x70, 0xfd, 0x37, 0x0d, 0x7f, 0x6f, 0x6a, 0x4b, 0x75, 0x3c, 0x11, 0xd1, 0x3e,
0x09, 0x83, 0x5e, 0xc4, 0x7a, 0x1d, 0xd0, 0x70, 0x05, 0x43, 0x52, 0xf9, 0x4a, 0xc1, 0xd4, 0x0a,
0x28, 0x33, 0xf4, 0x59, 0x96, 0x48, 0x0d, 0x3e, 0xd7, 0x5f, 0x36, 0xf4, 0x47, 0x59, 0xbc, 0xad,
0xa8, 0xe8, 0x6b, 0xb0, 0x64, 0x25, 0xd9, 0xfe, 0xbe, 0x20, 0x52, 0xa3, 0xce, 0xf5, 0x5b, 0x86,
0xf8, 0x13, 0x4d, 0xf3, 0x3e, 0x75, 0x61, 0xc5, 0x57, 0xd6, 0x25, 0x07, 0xe4, 0xff, 0x29, 0xaf,
0x1c, 0x17, 0xdf, 0x8b, 0xa7, 0x8a, 0xef, 0xda, 0xdc, 0xf1, 0x5d, 0x3f, 0x55, 0x7c, 0x37, 0x4e,
0x17, 0xdf, 0x70, 0xcc, 0x2b, 0xc3, 0x9f, 0x27, 0x9c, 0xf3, 0x1a, 0x44, 0xe7, 0x15, 0x70, 0x69,
0x68, 0x4a, 0xc5, 0xe6, 0x56, 0x67, 0xe6, 0xdd, 0xb8, 0xd3, 0x15, 0xbe, 0x12, 0x9a, 0xbe, 0x4f,
0x17, 0x4e, 0x7d, 0x9f, 0xfe, 0x00, 0x2e, 0x1e, 0x8d, 0x59, 0x6e, 0xcd, 0x11, 0x76, 0x16, 0xb5,
0xef, 0x2e, 0x4c, 0x07, 0x6d, 0x6e, 0xaf, 0x10, 0x7d, 0x07, 0xd6, 0x4a, 0x51, 0x3b, 0x9e, 0x58,
0x33, 0x3d, 0xfc, 0x98, 0x37, 0x9e, 0x72, 0x52, 0xdc, 0xd6, 0x4f, 0x8a, 0x5b, 0xef, 0x1f, 0x2e,
0x2c, 0x75, 0x49, 0x44, 0x24, 0xf9, 0xaa, 0xdc, 0x3b, 0xb6, 0xdc, 0xfb, 0x36, 0x20, 0x9a, 0xc8,
0x9b, 0x1f, 0x06, 0x29, 0xa7, 0x31, 0xe6, 0xa3, 0xe0, 0x29, 0x19, 0xe5, 0x09, 0xb1, 0xad, 0x39,
0xbb, 0x86, 0x71, 0x9f, 0x8c, 0xc4, 0x4b, 0xcb, 0xbf, 0x72, 0xbd, 0x65, 0x32, 0x60, 0x51, 0x6f,
0x7d, 0x0f, 0x5a, 0x13, 0x5b, 0xb4, 0x5e, 0x02, 0xd8, 0x66, 0x3a, 0xde, 0xd7, 0xfb, 0x8f, 0x03,
0x8d, 0x07, 0x0c, 0x87, 0xba, 0xf3, 0x39, 0xa3, 0x1b, 0x8b, 0xa2, 0xb6, 0x32, 0x5d, 0xd4, 0x5e,
0x82, 0x71, 0xf3, 0x62, 0x1d, 0x59, 0xea, 0x66, 0x4a, 0x5d, 0x49, 0x75, 0xb2, 0x2b, 0x79, 0x17,
0x9a, 0x54, 0x29, 0x14, 0xa4, 0x58, 0x0e, 0x4d, 0x4e, 0x6c, 0xf8, 0xa0, 0x49, 0xbb, 0x8a, 0xa2,
0xda, 0x96, 0x5c, 0x40, 0xb7, 0x2d, 0x8b, 0x73, 0xb7, 0x2d, 0x76, 0x11, 0xdd, 0xb6, 0xfc, 0xda,
0x01, 0xd0, 0x07, 0x57, 0xf9, 0xe0, 0xe8, 0xa2, 0xce, 0x59, 0x16, 0x55, 0xc9, 0x5a, 0x7b, 0x8a,
0x44, 0x58, 0x8e, 0x83, 0x4a, 0x58, 0xe3, 0x20, 0xe5, 0x35, 0xc3, 0xb2, 0x01, 0x25, 0xbc, 0xdf,
0x3b, 0x00, 0x3a, 0x2b, 0x18, 0x35, 0xa6, 0xe1, 0xe7, 0x9c, 0xdc, 0xd0, 0x55, 0x26, 0x4d, 0x77,
0x37, 0x37, 0xdd, 0x09, 0x2f, 0xa6, 0xa5, 0x0a, 0x3c, 0x3f, 0xbc, 0xb5, 0xae, 0xfe, 0xf6, 0xfe,
0xe0, 0x40, 0xcb, 0x6a, 0x67, 0x54, 0x9a, 0xf0, 0xb2, 0x33, 0xed, 0x65, 0x5d, 0xc6, 0xc4, 0x8c,
0x8f, 0x02, 0x41, 0x5f, 0x10, 0xab, 0x10, 0x18, 0xd2, 0x1e, 0x7d, 0x41, 0x26, 0xc0, 0xeb, 0x4e,
0x82, 0xf7, 0x2a, 0xac, 0x72, 0xd2, 0x27, 0x89, 0x8c, 0x46, 0x41, 0xcc, 0x42, 0xba, 0x4f, 0x49,
0xa8, 0xd1, 0x50, 0xf7, 0xdb, 0x39, 0xe3, 0xa1, 0xa5, 0x7b, 0xbf, 0x72, 0xa0, 0xf9, 0x50, 0x0c,
0x76, 0x99, 0xd0, 0x41, 0x86, 0x2e, 0x43, 0xcb, 0x26, 0x36, 0x13, 0xe1, 0x8e, 0x46, 0x58, 0xb3,
0x3f, 0x7e, 0x75, 0x54, 0xa9, 0x3d, 0x16, 0x03, 0x6b, 0xa6, 0x96, 0x6f, 0x06, 0x68, 0x1d, 0xea,
0xb1, 0x18, 0xe8, 0xaa, 0xdb, 0xc2, 0xb2, 0x18, 0xab, 0xb3, 0x8e, 0x2f, 0xab, 0xaa, 0xbe, 0xac,
0xc6, 0x04, 0xef, 0x33, 0x07, 0x90, 0x7d, 0xd5, 0x7c, 0xa5, 0x9f, 0x10, 0xda, 0xcb, 0xe5, 0x97,
0xd3, 0x8a, 0xc6, 0xf8, 0x04, 0x6d, 0x2a, 0x29, 0xb8, 0x47, 0x92, 0xc2, 0x55, 0x58, 0x0d, 0xc9,
0x3e, 0xce, 0xa2, 0xf2, 0xfd, 0x6a, 0x54, 0x6e, 0x5b, 0xc6, 0xc4, 0x2b, 0xfe, 0xf2, 0x36, 0x27,
0x21, 0x49, 0x24, 0xc5, 0x91, 0xfe, 0xb9, 0xb4, 0x0e, 0xf5, 0x4c, 0x28, 0x24, 0x14, 0xb6, 0x2b,
0xc6, 0xe8, 0x7d, 0x40, 0x24, 0xe9, 0xf3, 0x51, 0xaa, 0x40, 0x9c, 0x62, 0x21, 0x0e, 0x19, 0x0f,
0x6d, 0xa2, 0x5e, 0x2d, 0x38, 0xbb, 0x96, 0xa1, 0xda, 0x53, 0x49, 0x12, 0x9c, 0xc8, 0x3c, 0x5f,
0x9b, 0x91, 0x72, 0x3d, 0x15, 0x81, 0xc8, 0x52, 0xc2, 0xad, 0x5b, 0x6b, 0x54, 0xec, 0xa9, 0xa1,
0x4a, 0xe5, 0x62, 0x88, 0xb7, 0x3e, 0xba, 0x39, 0x5e, 0xde, 0xa4, 0xe8, 0x65, 0x43, 0xce, 0xd7,
0xf6, 0x3e, 0x81, 0xd5, 0x07, 0x54, 0xc8, 0x5d, 0x16, 0xd1, 0xfe, 0xe8, 0xcc, 0x37, 0x8e, 0x17,
0x01, 0x2a, 0x2f, 0x63, 0x7f, 0x61, 0x8c, 0x0b, 0x06, 0x67, 0xfe, 0x82, 0xe1, 0x32, 0xb4, 0x52,
0xbd, 0x8c, 0xfe, 0x61, 0x9a, 0x3b, 0xaf, 0x69, 0x68, 0xca, 0xb4, 0xc2, 0x1b, 0xc0, 0x85, 0xbd,
0x21, 0x3b, 0xdc, 0x66, 0xc9, 0x3e, 0x1d, 0x64, 0x1c, 0x2b, 0xc0, 0xbe, 0xc2, 0xdb, 0x57, 0x07,
0x6a, 0x29, 0x96, 0x2a, 0x6c, 0xad, 0x0f, 0xf2, 0xa1, 0xf7, 0xa9, 0x03, 0xeb, 0xb3, 0x76, 0x7a,
0x95, 0xf3, 0xdd, 0x83, 0xa5, 0xbe, 0x59, 0xce, 0xac, 0x36, 0xff, 0x4f, 0xc0, 0xc9, 0x79, 0x57,
0x3e, 0x86, 0x46, 0xf1, 0xc3, 0x19, 0xb5, 0xa1, 0xb5, 0x93, 0x50, 0xa9, 0x6b, 0x55, 0x9a, 0x0c,
0xda, 0x6f, 0xa0, 0x26, 0xd4, 0x7e, 0x4c, 0x70, 0x24, 0x87, 0xa3, 0xb6, 0x83, 0x5a, 0x50, 0xbf,
0xd3, 0x4b, 0x18, 0x8f, 0x71, 0xd4, 0xae, 0x5c, 0xd9, 0x82, 0xd5, 0x23, 0xef, 0x03, 0x4a, 0xc4,
0x67, 0x87, 0xca, 0x2c, 0x61, 0xfb, 0x0d, 0xb4, 0x02, 0xcd, 0x6d, 0x16, 0x65, 0x71, 0x62, 0x08,
0xce, 0xdd, 0x5b, 0xbf, 0xf8, 0x68, 0x40, 0xe5, 0x30, 0xeb, 0x29, 0xd5, 0xae, 0x1b, 0x5d, 0xdf,
0xa7, 0xcc, 0x7e, 0x5d, 0xcf, 0xd3, 0xde, 0x75, 0xad, 0x7e, 0x31, 0x4c, 0x7b, 0xbd, 0x45, 0x4d,
0xf9, 0xe0, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x32, 0x32, 0x7c, 0x82, 0xca, 0x1f, 0x00, 0x00,
// 2211 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x59, 0xcf, 0x73, 0x1b, 0x49,
0xf5, 0xdf, 0xd1, 0xc8, 0x96, 0xf4, 0x24, 0xcb, 0x72, 0xc7, 0xc9, 0x2a, 0x4e, 0xb2, 0xeb, 0xcc,
0x77, 0xbf, 0x60, 0x12, 0x36, 0x09, 0xde, 0xdd, 0x64, 0x0b, 0x28, 0x42, 0x62, 0x2d, 0xc1, 0x95,
0x1f, 0x98, 0x71, 0x48, 0x15, 0x5c, 0xa6, 0x5a, 0x9a, 0xb6, 0xd4, 0x64, 0x66, 0x7a, 0xdc, 0xdd,
0x63, 0x47, 0x39, 0x71, 0xe0, 0xc4, 0x16, 0xdc, 0xb8, 0x6c, 0x15, 0x9c, 0xb9, 0x70, 0xde, 0x1b,
0x54, 0x71, 0xe2, 0xc4, 0x89, 0x0b, 0xff, 0x0a, 0xc5, 0x81, 0xea, 0x1f, 0x33, 0xfa, 0x61, 0xd9,
0x91, 0x9d, 0xda, 0xdd, 0x50, 0xb5, 0xb7, 0xe9, 0xf7, 0x5e, 0x77, 0xbf, 0x7e, 0xef, 0xf3, 0x5e,
0xbf, 0xd7, 0x03, 0x4d, 0x9a, 0x48, 0xc2, 0x13, 0x1c, 0xdd, 0x48, 0x39, 0x93, 0x0c, 0x9d, 0x8f,
0x69, 0x74, 0x90, 0x09, 0x33, 0xba, 0x91, 0x33, 0xd7, 0x1a, 0x3d, 0x16, 0xc7, 0x2c, 0x31, 0xe4,
0xb5, 0x86, 0xe8, 0x0d, 0x48, 0x8c, 0xcd, 0xc8, 0xfb, 0x8b, 0x03, 0x4b, 0x5b, 0x2c, 0x4e, 0x59,
0x42, 0x12, 0xb9, 0x9d, 0xec, 0x31, 0x74, 0x01, 0x16, 0x13, 0x16, 0x92, 0xed, 0x4e, 0xdb, 0x59,
0x77, 0x36, 0x5c, 0xdf, 0x8e, 0x10, 0x82, 0x32, 0x67, 0x11, 0x69, 0x97, 0xd6, 0x9d, 0x8d, 0x9a,
0xaf, 0xbf, 0xd1, 0x5d, 0x00, 0x21, 0xb1, 0x24, 0x41, 0x8f, 0x85, 0xa4, 0xed, 0xae, 0x3b, 0x1b,
0xcd, 0xcd, 0xf5, 0x1b, 0x33, 0xb5, 0xb8, 0xb1, 0xab, 0x04, 0xb7, 0x58, 0x48, 0xfc, 0x9a, 0xc8,
0x3f, 0xd1, 0x0f, 0x01, 0xc8, 0x0b, 0xc9, 0x71, 0x40, 0x93, 0x3d, 0xd6, 0x2e, 0xaf, 0xbb, 0x1b,
0xf5, 0xcd, 0xab, 0x93, 0x0b, 0x58, 0xe5, 0x1f, 0x92, 0xe1, 0x33, 0x1c, 0x65, 0x64, 0x07, 0x53,
0xee, 0xd7, 0xf4, 0x24, 0xa5, 0xae, 0xf7, 0x2f, 0x07, 0x96, 0x8b, 0x03, 0xe8, 0x3d, 0x04, 0xfa,
0x2e, 0x2c, 0xe8, 0x2d, 0xf4, 0x09, 0xea, 0x9b, 0xef, 0x1d, 0xa3, 0xd1, 0xc4, 0xb9, 0x7d, 0x33,
0x05, 0xfd, 0x0c, 0xce, 0x89, 0xac, 0xdb, 0xcb, 0x59, 0x81, 0xa6, 0x8a, 0x76, 0x49, 0xab, 0x36,
0xdf, 0x4a, 0x68, 0x7c, 0x01, 0xab, 0xd2, 0x07, 0xb0, 0xa8, 0x56, 0xca, 0x84, 0xb6, 0x52, 0x7d,
0xf3, 0xd2, 0xcc, 0x43, 0xee, 0x6a, 0x11, 0xdf, 0x8a, 0x7a, 0x97, 0xe0, 0xe2, 0x03, 0x22, 0xa7,
0x4e, 0xe7, 0x93, 0xfd, 0x8c, 0x08, 0x69, 0x99, 0x4f, 0x69, 0x4c, 0x9e, 0xd2, 0xde, 0xf3, 0xad,
0x01, 0x4e, 0x12, 0x12, 0xe5, 0xcc, 0x2b, 0x70, 0xe9, 0x01, 0xd1, 0x13, 0xa8, 0x90, 0xb4, 0x27,
0xa6, 0xd8, 0xe7, 0xe1, 0xdc, 0x03, 0x22, 0x3b, 0xe1, 0x14, 0xf9, 0x19, 0x54, 0x9f, 0x28, 0x67,
0x2b, 0x18, 0xdc, 0x86, 0x0a, 0x0e, 0x43, 0x4e, 0x84, 0xb0, 0x56, 0xbc, 0x3c, 0x53, 0xe3, 0x7b,
0x46, 0xc6, 0xcf, 0x85, 0x67, 0xc1, 0xc4, 0xfb, 0x25, 0xc0, 0x76, 0x42, 0xe5, 0x0e, 0xe6, 0x38,
0x16, 0xc7, 0x02, 0xac, 0x03, 0x0d, 0x21, 0x31, 0x97, 0x41, 0xaa, 0xe5, 0xac, 0xc9, 0xe7, 0x40,
0x43, 0x5d, 0x4f, 0x33, 0xab, 0x7b, 0x3f, 0x07, 0xd8, 0x95, 0x9c, 0x26, 0xfd, 0x47, 0x54, 0x48,
0xb5, 0xd7, 0x81, 0x92, 0x53, 0x87, 0x70, 0x37, 0x6a, 0xbe, 0x1d, 0x8d, 0xb9, 0xa3, 0x34, 0xbf,
0x3b, 0xee, 0x42, 0x3d, 0x37, 0xf7, 0x63, 0xd1, 0x47, 0xb7, 0xa0, 0xdc, 0xc5, 0x82, 0x9c, 0x68,
0x9e, 0xc7, 0xa2, 0x7f, 0x1f, 0x0b, 0xe2, 0x6b, 0x49, 0xef, 0xcf, 0x25, 0x58, 0x9d, 0x70, 0x8b,
0x35, 0xfc, 0xe9, 0x97, 0x52, 0x66, 0x0e, 0xbb, 0xdb, 0x1d, 0xad, 0xbe, 0xeb, 0xeb, 0x6f, 0xe4,
0x41, 0xa3, 0xc7, 0xa2, 0x88, 0xf4, 0x24, 0x65, 0xc9, 0x76, 0x47, 0x23, 0xcd, 0xf5, 0x27, 0x68,
0x4a, 0x26, 0xc5, 0x5c, 0x52, 0x33, 0x14, 0x3a, 0xe4, 0x5c, 0x7f, 0x82, 0x86, 0xbe, 0x05, 0x2d,
0xc9, 0xf1, 0x01, 0x89, 0x02, 0x49, 0x63, 0x22, 0x24, 0x8e, 0xd3, 0xf6, 0xc2, 0xba, 0xb3, 0x51,
0xf6, 0x97, 0x0d, 0xfd, 0x69, 0x4e, 0x46, 0x37, 0xe1, 0x5c, 0x3f, 0xc3, 0x1c, 0x27, 0x92, 0x90,
0x31, 0xe9, 0x45, 0x2d, 0x8d, 0x0a, 0xd6, 0x68, 0xc2, 0x75, 0x58, 0x51, 0x62, 0x2c, 0x93, 0x63,
0xe2, 0x15, 0x2d, 0xde, 0xb2, 0x8c, 0x42, 0xd8, 0xfb, 0xdc, 0x81, 0xf3, 0x53, 0xf6, 0x12, 0x29,
0x4b, 0x04, 0x39, 0x83, 0xc1, 0xce, 0xe2, 0x71, 0x74, 0xc7, 0x24, 0x12, 0x15, 0xb4, 0x73, 0x62,
0xd1, 0xc8, 0x7b, 0xbf, 0x71, 0xe1, 0xed, 0x2d, 0x4e, 0x74, 0x9a, 0xcb, 0xad, 0x7f, 0x76, 0x67,
0xbf, 0x0d, 0x95, 0xb0, 0x1b, 0x24, 0x38, 0xce, 0xc3, 0x6a, 0x31, 0xec, 0x3e, 0xc1, 0x31, 0x41,
0xdf, 0x80, 0xe6, 0xc8, 0xbb, 0x8a, 0xa2, 0x7d, 0x5e, 0xf3, 0xa7, 0xa8, 0xe8, 0x3d, 0x58, 0x2a,
0x3c, 0xac, 0xc5, 0xca, 0x5a, 0x6c, 0x92, 0x58, 0x60, 0x6a, 0xe1, 0x04, 0x4c, 0x2d, 0xce, 0xc0,
0xd4, 0x3a, 0xd4, 0xc7, 0xf0, 0xa3, 0xbd, 0xe9, 0xfa, 0xe3, 0x24, 0x15, 0x86, 0xe6, 0xd6, 0x69,
0x57, 0xd7, 0x9d, 0x8d, 0x86, 0x6f, 0x47, 0xe8, 0x16, 0x9c, 0x3b, 0xa0, 0x5c, 0x66, 0x38, 0xb2,
0x99, 0x48, 0xe9, 0x21, 0xda, 0x35, 0x1d, 0xab, 0xb3, 0x58, 0x68, 0x13, 0x56, 0xd3, 0xc1, 0x50,
0xd0, 0xde, 0xd4, 0x14, 0xd0, 0x53, 0x66, 0xf2, 0xbc, 0xbf, 0x39, 0x70, 0xbe, 0xc3, 0x59, 0xfa,
0x46, 0xb8, 0x22, 0x37, 0x72, 0xf9, 0x04, 0x23, 0x2f, 0x1c, 0x35, 0xb2, 0xf7, 0xdb, 0x12, 0x5c,
0x30, 0x88, 0xda, 0xc9, 0x0d, 0xfb, 0x05, 0x9c, 0xe2, 0x9b, 0xb0, 0x3c, 0xda, 0xd5, 0x08, 0xcc,
0x3e, 0xc6, 0xff, 0x43, 0xb3, 0x70, 0xb0, 0x91, 0xfb, 0x72, 0x21, 0xe5, 0x7d, 0x5a, 0x82, 0x55,
0xe5, 0xd4, 0xaf, 0xad, 0xa1, 0xac, 0xf1, 0x47, 0x07, 0x90, 0x41, 0xc7, 0xbd, 0x88, 0x62, 0xf1,
0x55, 0xda, 0x62, 0x15, 0x16, 0xb0, 0xd2, 0xc1, 0x9a, 0xc0, 0x0c, 0x3c, 0x01, 0x2d, 0xe5, 0xad,
0x2f, 0x4a, 0xbb, 0x62, 0x53, 0x77, 0x7c, 0xd3, 0x3f, 0x38, 0xb0, 0x72, 0x2f, 0x92, 0x84, 0xbf,
0xa1, 0x46, 0xf9, 0x6b, 0x29, 0xf7, 0xda, 0x76, 0x12, 0x92, 0x17, 0x5f, 0xa5, 0x82, 0x57, 0x00,
0xf6, 0x28, 0x89, 0xc2, 0x71, 0xf4, 0xd6, 0x34, 0xe5, 0xb5, 0x90, 0xdb, 0x86, 0x8a, 0x5e, 0xa4,
0x40, 0x6d, 0x3e, 0x54, 0xd5, 0x9e, 0xa9, 0xfc, 0x6d, 0xb5, 0x57, 0x9d, 0xbb, 0xda, 0xd3, 0xd3,
0x6c, 0xb5, 0xf7, 0x8f, 0x32, 0x2c, 0x6d, 0x27, 0x82, 0x70, 0x79, 0x76, 0xe3, 0x5d, 0x86, 0x9a,
0x18, 0x60, 0xae, 0x0f, 0x6a, 0xcd, 0x37, 0x22, 0x8c, 0x9b, 0xd6, 0x7d, 0x95, 0x69, 0xcb, 0x73,
0x26, 0x87, 0x85, 0x93, 0x92, 0xc3, 0xe2, 0x09, 0x26, 0xae, 0xbc, 0x3a, 0x39, 0x54, 0x8f, 0xde,
0xbe, 0xea, 0x80, 0xa4, 0x1f, 0xab, 0xf6, 0xa4, 0xd3, 0xae, 0x69, 0xfe, 0x88, 0x80, 0xde, 0x01,
0x28, 0x2a, 0x31, 0x73, 0x8f, 0x96, 0xfd, 0x31, 0x8a, 0xba, 0xbb, 0x39, 0x3b, 0x54, 0xb5, 0x62,
0x5d, 0xd7, 0x8a, 0x76, 0x84, 0x3e, 0x84, 0x2a, 0x67, 0x87, 0x41, 0x88, 0x25, 0x6e, 0x37, 0xb4,
0xf3, 0x2e, 0xce, 0x34, 0xf6, 0xfd, 0x88, 0x75, 0xfd, 0x0a, 0x67, 0x87, 0x1d, 0x2c, 0x31, 0xba,
0x0b, 0x75, 0x8d, 0x00, 0x61, 0x26, 0x2e, 0xe9, 0x89, 0xef, 0x4c, 0x4e, 0xb4, 0x0d, 0xea, 0x8f,
0x94, 0x9c, 0x9a, 0xe4, 0x1b, 0x68, 0x0a, 0xbd, 0xc0, 0x45, 0xa8, 0x26, 0x59, 0x1c, 0x70, 0x76,
0x28, 0xda, 0x4d, 0x5d, 0x37, 0x56, 0x92, 0x2c, 0xf6, 0xd9, 0xa1, 0x40, 0xf7, 0xa1, 0x72, 0x40,
0xb8, 0xa0, 0x2c, 0x69, 0x2f, 0xeb, 0x56, 0x74, 0xe3, 0x98, 0x76, 0xcd, 0x20, 0x46, 0x2d, 0xf7,
0xcc, 0xc8, 0xfb, 0xf9, 0x44, 0xef, 0x9f, 0x65, 0x58, 0xda, 0x25, 0x98, 0xf7, 0x06, 0x67, 0x07,
0xd4, 0x2a, 0x2c, 0x70, 0xb2, 0x5f, 0x14, 0xe7, 0x66, 0x50, 0xf8, 0xd7, 0x3d, 0xc1, 0xbf, 0xe5,
0x39, 0x2a, 0xf6, 0x85, 0x19, 0x15, 0x7b, 0x0b, 0xdc, 0x50, 0x44, 0x1a, 0x3a, 0x35, 0x5f, 0x7d,
0xaa, 0x3a, 0x3b, 0x8d, 0x70, 0x8f, 0x0c, 0x58, 0x14, 0x12, 0x1e, 0xf4, 0x39, 0xcb, 0x4c, 0x9d,
0xdd, 0xf0, 0x5b, 0x63, 0x8c, 0x07, 0x8a, 0x8e, 0xee, 0x40, 0x35, 0x14, 0x51, 0x20, 0x87, 0x29,
0xd1, 0xf8, 0x69, 0x1e, 0x73, 0xcc, 0x8e, 0x88, 0x9e, 0x0e, 0x53, 0xe2, 0x57, 0x42, 0xf3, 0x81,
0x6e, 0xc1, 0xaa, 0x20, 0x9c, 0xe2, 0x88, 0xbe, 0x24, 0x61, 0x40, 0x5e, 0xa4, 0x3c, 0x48, 0x23,
0x9c, 0x68, 0x90, 0x35, 0x7c, 0x34, 0xe2, 0x7d, 0xf2, 0x22, 0xe5, 0x3b, 0x11, 0x4e, 0xd0, 0x06,
0xb4, 0x58, 0x26, 0xd3, 0x4c, 0x06, 0x16, 0x06, 0x34, 0xd4, 0x98, 0x73, 0xfd, 0xa6, 0xa1, 0x6b,
0xaf, 0x8b, 0xed, 0x70, 0x66, 0x17, 0x52, 0x3f, 0x55, 0x17, 0xd2, 0x38, 0x5d, 0x17, 0xb2, 0x34,
0xbb, 0x0b, 0x41, 0x4d, 0x28, 0x25, 0xfb, 0x1a, 0x6b, 0xae, 0x5f, 0x4a, 0xf6, 0x95, 0x23, 0x25,
0x4b, 0x9f, 0x6b, 0x8c, 0xb9, 0xbe, 0xfe, 0x56, 0x41, 0x14, 0x13, 0xc9, 0x69, 0x4f, 0x99, 0xa5,
0xdd, 0xd2, 0x7e, 0x18, 0xa3, 0x78, 0xff, 0x71, 0x47, 0xb0, 0x12, 0x59, 0x24, 0xc5, 0x97, 0xd5,
0xc1, 0x14, 0x58, 0x74, 0xc7, 0xb1, 0xf8, 0x2e, 0xd4, 0x8d, 0x72, 0xc6, 0xe7, 0xe5, 0x69, 0x7d,
0x95, 0x80, 0x8a, 0xb2, 0xfd, 0x8c, 0x70, 0x4a, 0x84, 0x4d, 0xfb, 0x90, 0x64, 0xf1, 0x4f, 0x0d,
0x05, 0x9d, 0x83, 0x05, 0xc9, 0xd2, 0xe0, 0x79, 0x9e, 0xae, 0x24, 0x4b, 0x1f, 0xa2, 0xef, 0xc3,
0x9a, 0x20, 0x38, 0x22, 0x61, 0x50, 0xa4, 0x17, 0x11, 0x08, 0x7d, 0x6c, 0x12, 0xb6, 0x2b, 0xda,
0xcd, 0x6d, 0x23, 0xb1, 0x5b, 0x08, 0xec, 0x5a, 0xbe, 0xf2, 0x62, 0xcf, 0x94, 0xed, 0x13, 0xd3,
0xaa, 0xba, 0xb2, 0x47, 0x23, 0x56, 0x31, 0xe1, 0x63, 0x68, 0xf7, 0x23, 0xd6, 0xc5, 0x51, 0x70,
0x64, 0x57, 0xdd, 0x42, 0xb8, 0xfe, 0x05, 0xc3, 0xdf, 0x9d, 0xda, 0x52, 0x1d, 0x4f, 0x44, 0xb4,
0x47, 0xc2, 0xa0, 0x1b, 0xb1, 0x6e, 0x1b, 0x34, 0x5c, 0xc1, 0x90, 0x54, 0xbe, 0x52, 0x30, 0xb5,
0x02, 0xca, 0x0c, 0x3d, 0x96, 0x25, 0x52, 0x83, 0xcf, 0xf5, 0x9b, 0x86, 0xfe, 0x24, 0x8b, 0xb7,
0x14, 0x15, 0xfd, 0x1f, 0x2c, 0x59, 0x49, 0xb6, 0xb7, 0x27, 0x88, 0xd4, 0xa8, 0x73, 0xfd, 0x86,
0x21, 0xfe, 0x44, 0xd3, 0xbc, 0xcf, 0x5c, 0x58, 0xf6, 0x95, 0x75, 0xc9, 0x01, 0xf9, 0x5f, 0xca,
0x2b, 0xc7, 0xc5, 0xf7, 0xe2, 0xa9, 0xe2, 0xbb, 0x32, 0x77, 0x7c, 0x57, 0x4f, 0x15, 0xdf, 0xb5,
0xd3, 0xc5, 0x37, 0x1c, 0xf3, 0xca, 0xf0, 0xa7, 0x09, 0xe7, 0xbc, 0x01, 0xd1, 0x79, 0x0d, 0x5c,
0x1a, 0x9a, 0x52, 0xb1, 0xbe, 0xd9, 0x9e, 0x79, 0x37, 0x6e, 0x77, 0x84, 0xaf, 0x84, 0xa6, 0xef,
0xd3, 0x85, 0x53, 0xdf, 0xa7, 0x3f, 0x80, 0x4b, 0x47, 0x63, 0x96, 0x5b, 0x73, 0x84, 0xed, 0x45,
0xed, 0xbb, 0x8b, 0xd3, 0x41, 0x9b, 0xdb, 0x2b, 0x44, 0xdf, 0x81, 0xd5, 0xb1, 0xa8, 0x1d, 0x4d,
0xac, 0x98, 0x1e, 0x7e, 0xc4, 0x1b, 0x4d, 0x39, 0x29, 0x6e, 0xab, 0x27, 0xc5, 0xad, 0xf7, 0x77,
0x17, 0x96, 0x3a, 0x24, 0x22, 0x92, 0x7c, 0x5d, 0xee, 0x1d, 0x5b, 0xee, 0x7d, 0x1b, 0x10, 0x4d,
0xe4, 0xed, 0x0f, 0x83, 0x94, 0xd3, 0x18, 0xf3, 0x61, 0xf0, 0x9c, 0x0c, 0xf3, 0x84, 0xd8, 0xd2,
0x9c, 0x1d, 0xc3, 0x78, 0x48, 0x86, 0xe2, 0x95, 0xe5, 0xdf, 0x78, 0xbd, 0x65, 0x32, 0x60, 0x51,
0x6f, 0x7d, 0x0f, 0x1a, 0x13, 0x5b, 0x34, 0x5e, 0x01, 0xd8, 0x7a, 0x3a, 0xda, 0xd7, 0xfb, 0xb7,
0x03, 0xb5, 0x47, 0x0c, 0x87, 0xba, 0xf3, 0x39, 0xa3, 0x1b, 0x8b, 0xa2, 0xb6, 0x34, 0x5d, 0xd4,
0x5e, 0x86, 0x51, 0xf3, 0x62, 0x1d, 0x39, 0xd6, 0xcd, 0x8c, 0x75, 0x25, 0xe5, 0xc9, 0xae, 0xe4,
0x5d, 0xa8, 0x53, 0xa5, 0x50, 0x90, 0x62, 0x39, 0x30, 0x39, 0xb1, 0xe6, 0x83, 0x26, 0xed, 0x28,
0x8a, 0x6a, 0x5b, 0x72, 0x01, 0xdd, 0xb6, 0x2c, 0xce, 0xdd, 0xb6, 0xd8, 0x45, 0x74, 0xdb, 0xf2,
0x6b, 0x07, 0x40, 0x1f, 0x5c, 0xe5, 0x83, 0xa3, 0x8b, 0x3a, 0x67, 0x59, 0x54, 0x25, 0x6b, 0xed,
0x29, 0x12, 0x61, 0x39, 0x0a, 0x2a, 0x61, 0x8d, 0x83, 0x94, 0xd7, 0x0c, 0xcb, 0x06, 0x94, 0xf0,
0x7e, 0xe7, 0x00, 0xe8, 0xac, 0x60, 0xd4, 0x98, 0x86, 0x9f, 0x73, 0x72, 0x43, 0x57, 0x9a, 0x34,
0xdd, 0xfd, 0xdc, 0x74, 0x27, 0xbc, 0x98, 0x8e, 0x55, 0xe0, 0xf9, 0xe1, 0xad, 0x75, 0xf5, 0xb7,
0xf7, 0x7b, 0x07, 0x1a, 0x56, 0x3b, 0xa3, 0xd2, 0x84, 0x97, 0x9d, 0x69, 0x2f, 0xeb, 0x32, 0x26,
0x66, 0x7c, 0x18, 0x08, 0xfa, 0x92, 0x58, 0x85, 0xc0, 0x90, 0x76, 0xe9, 0x4b, 0x32, 0x01, 0x5e,
0x77, 0x12, 0xbc, 0xd7, 0x61, 0x85, 0x93, 0x1e, 0x49, 0x64, 0x34, 0x0c, 0x62, 0x16, 0xd2, 0x3d,
0x4a, 0x42, 0x8d, 0x86, 0xaa, 0xdf, 0xca, 0x19, 0x8f, 0x2d, 0xdd, 0xfb, 0x95, 0x03, 0xf5, 0xc7,
0xa2, 0xbf, 0xc3, 0x84, 0x0e, 0x32, 0x74, 0x15, 0x1a, 0x36, 0xb1, 0x99, 0x08, 0x77, 0x34, 0xc2,
0xea, 0xbd, 0xd1, 0xab, 0xa3, 0x4a, 0xed, 0xb1, 0xe8, 0x5b, 0x33, 0x35, 0x7c, 0x33, 0x40, 0x6b,
0x50, 0x8d, 0x45, 0x5f, 0x57, 0xdd, 0x16, 0x96, 0xc5, 0x58, 0x9d, 0x75, 0x74, 0x59, 0x95, 0xf5,
0x65, 0x35, 0x22, 0x78, 0x9f, 0x3b, 0x80, 0xec, 0xab, 0xe6, 0x6b, 0xfd, 0x84, 0xd0, 0x5e, 0x1e,
0x7f, 0x39, 0x2d, 0x69, 0x8c, 0x4f, 0xd0, 0xa6, 0x92, 0x82, 0x7b, 0x24, 0x29, 0x5c, 0x87, 0x95,
0x90, 0xec, 0xe1, 0x2c, 0x1a, 0xbf, 0x5f, 0x8d, 0xca, 0x2d, 0xcb, 0x98, 0x78, 0xc5, 0x6f, 0x6e,
0x71, 0x12, 0x92, 0x44, 0x52, 0x1c, 0xe9, 0x9f, 0x4b, 0x6b, 0x50, 0xcd, 0x84, 0x42, 0x42, 0x61,
0xbb, 0x62, 0x8c, 0xde, 0x07, 0x44, 0x92, 0x1e, 0x1f, 0xa6, 0x0a, 0xc4, 0x29, 0x16, 0xe2, 0x90,
0xf1, 0xd0, 0x26, 0xea, 0x95, 0x82, 0xb3, 0x63, 0x19, 0xaa, 0x3d, 0x95, 0x24, 0xc1, 0x89, 0xcc,
0xf3, 0xb5, 0x19, 0x29, 0xd7, 0x53, 0x11, 0x88, 0x2c, 0x25, 0xdc, 0xba, 0xb5, 0x42, 0xc5, 0xae,
0x1a, 0xaa, 0x54, 0x2e, 0x06, 0x78, 0xf3, 0xa3, 0xdb, 0xa3, 0xe5, 0x4d, 0x8a, 0x6e, 0x1a, 0x72,
0xbe, 0xb6, 0xf7, 0x09, 0xac, 0x3c, 0xa2, 0x42, 0xee, 0xb0, 0x88, 0xf6, 0x86, 0x67, 0xbe, 0x71,
0xbc, 0x4f, 0x1d, 0x40, 0xe3, 0xeb, 0xd8, 0x7f, 0x18, 0xa3, 0x8a, 0xc1, 0x99, 0xbf, 0x62, 0xb8,
0x0a, 0x8d, 0x54, 0x2f, 0xa3, 0xff, 0x98, 0xe6, 0xde, 0xab, 0x1b, 0x9a, 0xb2, 0xad, 0x40, 0x57,
0x00, 0x94, 0x31, 0x03, 0xce, 0x22, 0x62, 0x9c, 0x57, 0xf3, 0x6b, 0x8a, 0xe2, 0x2b, 0x82, 0xd7,
0x87, 0x8b, 0xbb, 0x03, 0x76, 0xb8, 0xc5, 0x92, 0x3d, 0xda, 0xcf, 0x38, 0x56, 0x80, 0x7e, 0x8d,
0xb7, 0xb1, 0x36, 0x54, 0x52, 0x2c, 0x55, 0x58, 0x5b, 0x1f, 0xe5, 0x43, 0xef, 0x33, 0x07, 0xd6,
0x66, 0xed, 0xf4, 0x3a, 0xc7, 0x7f, 0x00, 0x4b, 0x3d, 0xb3, 0x9c, 0x59, 0x6d, 0xfe, 0x9f, 0x84,
0x93, 0xf3, 0xae, 0x7d, 0x0c, 0xb5, 0xe2, 0x87, 0x34, 0x6a, 0x41, 0x63, 0x3b, 0xa1, 0x52, 0xd7,
0xb2, 0x34, 0xe9, 0xb7, 0xde, 0x42, 0x75, 0xa8, 0xfc, 0x98, 0xe0, 0x48, 0x0e, 0x86, 0x2d, 0x07,
0x35, 0xa0, 0x7a, 0xaf, 0x9b, 0x30, 0x1e, 0xe3, 0xa8, 0x55, 0xba, 0xb6, 0x09, 0x2b, 0x47, 0xde,
0x0f, 0x94, 0x88, 0xcf, 0x0e, 0x95, 0x59, 0xc2, 0xd6, 0x5b, 0x68, 0x19, 0xea, 0x5b, 0x2c, 0xca,
0xe2, 0xc4, 0x10, 0x9c, 0xfb, 0x77, 0x7e, 0xf1, 0x51, 0x9f, 0xca, 0x41, 0xd6, 0x55, 0xaa, 0xdd,
0x34, 0xba, 0xbe, 0x4f, 0x99, 0xfd, 0xba, 0x99, 0xa7, 0xc5, 0x9b, 0x5a, 0xfd, 0x62, 0x98, 0x76,
0xbb, 0x8b, 0x9a, 0xf2, 0xc1, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x10, 0x68, 0x86, 0x3f, 0xea,
0x1f, 0x00, 0x00,
}

View File

@ -81,7 +81,6 @@ service MilvusService {
rpc OperateUserRole(OperateUserRoleRequest) returns (common.Status) {}
rpc SelectRole(SelectRoleRequest) returns (SelectRoleResponse) {}
rpc SelectUser(SelectUserRequest) returns (SelectUserResponse) {}
rpc SelectResource(SelectResourceRequest) returns (SelectResourceResponse) {}
rpc OperatePrivilege(OperatePrivilegeRequest) returns (common.Status) {}
rpc SelectGrant(SelectGrantRequest) returns (SelectGrantResponse) {}
}
@ -111,9 +110,9 @@ message AlterAliasRequest{
*/
message CreateCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeCreate
resource_name_index: 3
object_type: Global
object_privilege: PrivilegeCreateCollection
object_name_index: -1
};
// Not useful for now
common.MsgBase base = 1;
@ -135,9 +134,9 @@ message CreateCollectionRequest {
*/
message DropCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeDrop
resource_name_index: 3
object_type: Global
object_privilege: PrivilegeDropCollection
object_name_index: -1
};
// Not useful for now
common.MsgBase base = 1;
@ -151,11 +150,6 @@ message DropCollectionRequest {
* Check collection exist in milvus or not.
*/
message HasCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRead
resource_name_index: 3
};
// Not useful for now
common.MsgBase base = 1;
// Not useful for now
@ -182,9 +176,9 @@ message StringResponse {
*/
message DescribeCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRead
resource_name_index: 3
object_type: Global
object_privilege: PrivilegeDescribeCollection
object_name_index: -1
};
// Not useful for now
common.MsgBase base = 1;
@ -233,9 +227,9 @@ message DescribeCollectionResponse {
*/
message LoadCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeLoad
resource_name_index: 3
object_type: Collection
object_privilege: PrivilegeLoad
object_name_index: 3
};
// Not useful for now
common.MsgBase base = 1;
@ -252,9 +246,9 @@ message LoadCollectionRequest {
*/
message ReleaseCollectionRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRelease
resource_name_index: 3
object_type: Collection
object_privilege: PrivilegeRelease
object_name_index: 3
};
// Not useful for now
common.MsgBase base = 1;
@ -269,11 +263,6 @@ message ReleaseCollectionRequest {
* WARNING: This API is experimental and not useful for now.
*/
message GetStatisticsRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRead
resource_name_index: 3
};
// Not useful for now
common.MsgBase base = 1;
// Not useful for now
@ -301,11 +290,6 @@ message GetStatisticsResponse {
* Get collection statistics like row_count.
*/
message GetCollectionStatisticsRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRead
resource_name_index: 3
};
// Not useful for now
common.MsgBase base = 1;
// Not useful for now
@ -339,8 +323,9 @@ enum ShowType {
*/
message ShowCollectionsRequest {
option (common.privilege_ext_obj) = {
resource_type: Collection
resource_privilege: PrivilegeRead
object_type: Global
object_privilege: PrivilegeShowCollections
object_name_index: -1
};
// Not useful for now
common.MsgBase base = 1;
@ -633,6 +618,11 @@ message DropIndexRequest {
}
message InsertRequest {
option (common.privilege_ext_obj) = {
object_type: Collection
object_privilege: PrivilegeInsert
object_name_index: 3
};
common.MsgBase base = 1;
string db_name = 2;
string collection_name = 3;
@ -655,6 +645,11 @@ message MutationResult {
}
message DeleteRequest {
option (common.privilege_ext_obj) = {
object_type: Collection
object_privilege: PrivilegeDelete
object_name_index: 3
};
common.MsgBase base = 1;
string db_name = 2;
string collection_name = 3;
@ -834,6 +829,11 @@ message LoadBalanceRequest {
}
message ManualCompactionRequest {
option (common.privilege_ext_obj) = {
object_type: Collection
object_privilege: PrivilegeCompaction
object_name_index: 1
};
int64 collectionID = 1;
uint64 timetravel = 2;
}
@ -1075,60 +1075,33 @@ message SelectUserResponse {
// Not useful for now
common.Status status = 1;
// user result array
repeated UserResult result = 2;
repeated UserResult results = 2;
}
message ResourceEntity {
string type = 1;
message ObjectEntity {
string name = 1;
}
message PrivilegeEntity {
string name = 1;
}
message SelectResourceRequest {
// Not useful for now
common.MsgBase base = 1;
// resource
ResourceEntity entity = 2;
// include privilege info
bool include_privilege_info = 3;
}
message ResourceResult {
ResourceEntity resource = 1;
repeated PrivilegeEntity privileges = 2;
}
message SelectResourceResponse {
// Not useful for now
common.Status status = 1;
// resource result array
repeated ResourceResult results = 2;
}
message PrincipalEntity {
// principal type, including user, role
string principal_type = 1;
// principal, including user entity or role entity
oneof principal {
UserEntity user = 2;
RoleEntity role = 3;
}
}
message GrantorEntity {
UserEntity user = 1;
PrivilegeEntity privilege = 2;
}
message GrantPrivilegeEntity {
repeated GrantorEntity entities = 1;
}
message GrantEntity {
// principal
PrincipalEntity principal = 1;
// resource
ResourceEntity resource = 2;
// resource name
string resource_name = 3;
// role
RoleEntity role = 1;
// object
ObjectEntity object = 2;
// object name
string object_name = 3;
// privilege
GrantorEntity grantor = 4;
}

File diff suppressed because it is too large Load Diff

View File

@ -131,7 +131,6 @@ service RootCoord {
rpc OperateUserRole(milvus.OperateUserRoleRequest) returns (common.Status) {}
rpc SelectRole(milvus.SelectRoleRequest) returns (milvus.SelectRoleResponse) {}
rpc SelectUser(milvus.SelectUserRequest) returns (milvus.SelectUserResponse) {}
rpc SelectResource(milvus.SelectResourceRequest) returns (milvus.SelectResourceResponse) {}
rpc OperatePrivilege(milvus.OperatePrivilegeRequest) returns (common.Status) {}
rpc SelectGrant(milvus.SelectGrantRequest) returns (milvus.SelectGrantResponse) {}
rpc ListPolicy(internal.ListPolicyRequest) returns (internal.ListPolicyResponse) {}

View File

@ -676,110 +676,109 @@ func init() {
func init() { proto.RegisterFile("root_coord.proto", fileDescriptor_4513485a144f6b06) }
var fileDescriptor_4513485a144f6b06 = []byte{
// 1637 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x73, 0xd3, 0x46,
0x14, 0xc6, 0x36, 0xb9, 0x1d, 0x3b, 0x71, 0xd8, 0x21, 0xe0, 0x1a, 0xda, 0x1a, 0x97, 0x82, 0xc3,
0xc5, 0x61, 0xc2, 0x0c, 0xa5, 0xbc, 0x91, 0x98, 0x06, 0x4f, 0xc9, 0x10, 0x64, 0xe8, 0xd0, 0x0b,
0xe3, 0x6e, 0xa4, 0x83, 0xa3, 0x89, 0xac, 0x35, 0xda, 0x75, 0x2e, 0x8f, 0x9d, 0xe9, 0x7b, 0xff,
0x53, 0xfb, 0x53, 0xfa, 0xd6, 0x5f, 0xd1, 0x59, 0xad, 0x24, 0x4b, 0xb2, 0xd6, 0x51, 0x80, 0x37,
0xed, 0xee, 0xb7, 0xdf, 0x77, 0xf6, 0x9c, 0xdd, 0xb3, 0x67, 0x05, 0xab, 0x1e, 0x63, 0xa2, 0x6f,
0x32, 0xe6, 0x59, 0xed, 0x91, 0xc7, 0x04, 0x23, 0x57, 0x86, 0xb6, 0x73, 0x34, 0xe6, 0xaa, 0xd5,
0x96, 0xc3, 0xfe, 0x68, 0xbd, 0x62, 0xb2, 0xe1, 0x90, 0xb9, 0xaa, 0xbf, 0x5e, 0x89, 0xa3, 0xea,
0x2b, 0xb6, 0x2b, 0xd0, 0x73, 0xa9, 0x13, 0xb4, 0xcb, 0x23, 0x8f, 0x9d, 0x9c, 0x06, 0x8d, 0x55,
0x8b, 0x0a, 0x1a, 0x97, 0xa8, 0x57, 0x51, 0x98, 0x56, 0x7f, 0x88, 0x82, 0x06, 0x1d, 0x97, 0x6c,
0xd7, 0xc2, 0x93, 0x38, 0xa6, 0xd9, 0x87, 0xb5, 0xa7, 0x8e, 0xc3, 0xcc, 0xd7, 0xf6, 0x10, 0xb9,
0xa0, 0xc3, 0x91, 0x81, 0x1f, 0xc6, 0xc8, 0x05, 0x79, 0x00, 0x17, 0xf7, 0x29, 0xc7, 0x5a, 0xa1,
0x51, 0x68, 0x95, 0x37, 0xaf, 0xb7, 0x13, 0xe6, 0x06, 0x36, 0xee, 0xf2, 0xc1, 0x16, 0xe5, 0x68,
0xf8, 0x48, 0x72, 0x19, 0xe6, 0x4c, 0x36, 0x76, 0x45, 0xad, 0xd4, 0x28, 0xb4, 0x96, 0x0d, 0xd5,
0x68, 0xfe, 0x51, 0x80, 0x2b, 0x69, 0x05, 0x3e, 0x62, 0x2e, 0x47, 0xf2, 0x10, 0xe6, 0xb9, 0xa0,
0x62, 0xcc, 0x03, 0x91, 0x6b, 0x99, 0x22, 0x3d, 0x1f, 0x62, 0x04, 0x50, 0x72, 0x1d, 0x96, 0x44,
0xc8, 0x54, 0x2b, 0x36, 0x0a, 0xad, 0x8b, 0xc6, 0xa4, 0x43, 0x63, 0xc3, 0x5b, 0x58, 0xf1, 0x4d,
0xe8, 0x76, 0x3e, 0xc3, 0xea, 0x8a, 0x71, 0x66, 0x07, 0xaa, 0x11, 0xf3, 0xa7, 0xac, 0x6a, 0x05,
0x8a, 0xdd, 0x8e, 0x4f, 0x5d, 0x32, 0x8a, 0xdd, 0x8e, 0x66, 0x1d, 0x7f, 0x17, 0xa1, 0xd2, 0x1d,
0x8e, 0x98, 0x27, 0x0c, 0xe4, 0x63, 0x47, 0x7c, 0x9c, 0xd6, 0x55, 0x58, 0x10, 0x94, 0x1f, 0xf6,
0x6d, 0x2b, 0x10, 0x9c, 0x97, 0xcd, 0xae, 0x45, 0xbe, 0x86, 0xb2, 0xdc, 0x43, 0x2e, 0xb3, 0x50,
0x0e, 0x96, 0xfc, 0x41, 0x08, 0xbb, 0xba, 0x16, 0x79, 0x04, 0x73, 0x92, 0x03, 0x6b, 0x17, 0x1b,
0x85, 0xd6, 0xca, 0x66, 0x23, 0x53, 0x4d, 0x19, 0x28, 0x35, 0xd1, 0x50, 0x70, 0x52, 0x87, 0x45,
0x8e, 0x83, 0x21, 0xba, 0x82, 0xd7, 0xe6, 0x1a, 0xa5, 0x56, 0xc9, 0x88, 0xda, 0xe4, 0x0b, 0x58,
0xa4, 0x63, 0xc1, 0xfa, 0xb6, 0xc5, 0x6b, 0xf3, 0xfe, 0xd8, 0x82, 0x6c, 0x77, 0x2d, 0x4e, 0xae,
0xc1, 0x92, 0xc7, 0x8e, 0xfb, 0xca, 0x11, 0x0b, 0xbe, 0x35, 0x8b, 0x1e, 0x3b, 0xde, 0x96, 0x6d,
0xf2, 0x1d, 0xcc, 0xd9, 0xee, 0x7b, 0xc6, 0x6b, 0x8b, 0x8d, 0x52, 0xab, 0xbc, 0x79, 0x23, 0xd3,
0x96, 0x1f, 0xf1, 0xf4, 0x27, 0xea, 0x8c, 0x71, 0x8f, 0xda, 0x9e, 0xa1, 0xf0, 0xcd, 0xbf, 0x0a,
0x70, 0xb5, 0x83, 0xdc, 0xf4, 0xec, 0x7d, 0xec, 0x05, 0x56, 0x7c, 0xfc, 0xb6, 0x68, 0x42, 0xc5,
0x64, 0x8e, 0x83, 0xa6, 0xb0, 0x99, 0x1b, 0x85, 0x30, 0xd1, 0x47, 0xbe, 0x02, 0x08, 0x96, 0xdb,
0xed, 0xf0, 0x5a, 0xc9, 0x5f, 0x64, 0xac, 0xa7, 0x39, 0x86, 0x6a, 0x60, 0x88, 0x24, 0xee, 0xba,
0xef, 0xd9, 0x14, 0x6d, 0x21, 0x83, 0xb6, 0x01, 0xe5, 0x11, 0xf5, 0x84, 0x9d, 0x50, 0x8e, 0x77,
0xc9, 0xb3, 0x12, 0xc9, 0x04, 0xe1, 0x9c, 0x74, 0x34, 0xff, 0x2d, 0x42, 0x25, 0xd0, 0x95, 0x9a,
0x9c, 0x74, 0x60, 0x49, 0xae, 0xa9, 0x2f, 0xfd, 0x14, 0xb8, 0xe0, 0x76, 0x3b, 0x3b, 0x4d, 0xb5,
0x53, 0x06, 0x1b, 0x8b, 0xfb, 0xa1, 0xe9, 0x1d, 0x28, 0xab, 0x34, 0xa3, 0xc2, 0x53, 0xf4, 0xc3,
0xf3, 0x4d, 0x92, 0x47, 0x26, 0xa6, 0x76, 0xa4, 0x6d, 0xe1, 0x89, 0xcf, 0x01, 0x76, 0xf8, 0xc9,
0x09, 0xc2, 0x25, 0x3c, 0x11, 0x1e, 0xed, 0xc7, 0xb9, 0x4a, 0x3e, 0xd7, 0xf7, 0x67, 0xd8, 0xe4,
0x13, 0xb4, 0x9f, 0xc9, 0xd9, 0x11, 0x37, 0x7f, 0xe6, 0x0a, 0xef, 0xd4, 0xa8, 0x62, 0xb2, 0xb7,
0xfe, 0x3b, 0x5c, 0xce, 0x02, 0x92, 0x55, 0x28, 0x1d, 0xe2, 0x69, 0xe0, 0x76, 0xf9, 0x49, 0x36,
0x61, 0xee, 0x48, 0x6e, 0x25, 0xdf, 0xcf, 0x53, 0x7b, 0xc3, 0x5f, 0xd0, 0x64, 0x25, 0x0a, 0xfa,
0xa4, 0xf8, 0xb8, 0xd0, 0xfc, 0xa7, 0x08, 0xb5, 0xe9, 0xed, 0xf6, 0x29, 0xb9, 0x22, 0xcf, 0x96,
0x1b, 0xc0, 0x72, 0x10, 0xe8, 0x84, 0xeb, 0xb6, 0x74, 0xae, 0xd3, 0x59, 0x98, 0xf0, 0xa9, 0xf2,
0x61, 0x85, 0xc7, 0xba, 0xea, 0x08, 0x97, 0xa6, 0x20, 0x19, 0xde, 0x7b, 0x92, 0xf4, 0xde, 0xcd,
0x3c, 0x21, 0x8c, 0x7b, 0xd1, 0x82, 0xcb, 0x3b, 0x28, 0xb6, 0x3d, 0xb4, 0xd0, 0x15, 0x36, 0x75,
0x3e, 0xfe, 0xc0, 0xd6, 0x61, 0x71, 0xcc, 0xe5, 0x25, 0x3a, 0x54, 0xc6, 0x2c, 0x19, 0x51, 0xbb,
0xf9, 0x67, 0x01, 0xd6, 0x52, 0x32, 0x9f, 0x12, 0xa8, 0x19, 0x52, 0x72, 0x6c, 0x44, 0x39, 0x3f,
0x66, 0x9e, 0x4a, 0xb4, 0x4b, 0x46, 0xd4, 0xde, 0xfc, 0xef, 0x26, 0x2c, 0x19, 0x8c, 0x89, 0x6d,
0xe9, 0x12, 0x32, 0x02, 0x22, 0x6d, 0x62, 0xc3, 0x11, 0x73, 0xd1, 0x55, 0x89, 0x95, 0x93, 0x07,
0x49, 0x03, 0xa2, 0xc2, 0x60, 0x1a, 0x1a, 0xb8, 0xaa, 0x7e, 0x4b, 0x33, 0x23, 0x05, 0x6f, 0x5e,
0x20, 0x43, 0x5f, 0x51, 0xde, 0xd7, 0xaf, 0x6d, 0xf3, 0x70, 0xfb, 0x80, 0xba, 0x2e, 0x3a, 0xb3,
0x14, 0x53, 0xd0, 0x50, 0x31, 0x75, 0xe8, 0x83, 0x46, 0x4f, 0x78, 0xb6, 0x3b, 0x08, 0x3d, 0xdb,
0xbc, 0x40, 0x3e, 0xf8, 0xb1, 0x95, 0xea, 0x36, 0x17, 0xb6, 0xc9, 0x43, 0xc1, 0x4d, 0xbd, 0xe0,
0x14, 0xf8, 0x9c, 0x92, 0x7d, 0x58, 0xdd, 0xf6, 0x90, 0x0a, 0xdc, 0x8e, 0x0e, 0x0d, 0xb9, 0x97,
0x39, 0x35, 0x0d, 0x0b, 0x85, 0x66, 0x6d, 0x80, 0xe6, 0x05, 0xf2, 0x2b, 0xac, 0x74, 0x3c, 0x36,
0x8a, 0xd1, 0xdf, 0xc9, 0xa4, 0x4f, 0x82, 0x72, 0x92, 0xf7, 0x61, 0xf9, 0x39, 0xe5, 0x31, 0xee,
0xf5, 0x4c, 0xee, 0x04, 0x26, 0xa4, 0xbe, 0x91, 0x09, 0xdd, 0x62, 0xcc, 0x89, 0xb9, 0xe7, 0x18,
0x48, 0x98, 0x10, 0x62, 0x2a, 0xed, 0xec, 0x15, 0x4c, 0x01, 0x43, 0xa9, 0x8d, 0xdc, 0xf8, 0x48,
0xf8, 0x0d, 0x94, 0x95, 0xc3, 0x9f, 0x3a, 0x36, 0xe5, 0xe4, 0xf6, 0x8c, 0x90, 0xf8, 0x88, 0x9c,
0x0e, 0x7b, 0x05, 0x4b, 0xd2, 0xd1, 0x8a, 0xf4, 0x5b, 0x6d, 0x20, 0xce, 0x43, 0xd9, 0x03, 0x78,
0xea, 0x08, 0xf4, 0x14, 0xe7, 0xad, 0x4c, 0xce, 0x09, 0x20, 0x27, 0xa9, 0x0b, 0xd5, 0xde, 0x81,
0x2c, 0x70, 0x42, 0xd7, 0x70, 0x72, 0x37, 0x7b, 0x43, 0x27, 0x51, 0x21, 0xfd, 0xbd, 0x7c, 0xe0,
0xc8, 0xdd, 0xef, 0xa0, 0xaa, 0x9c, 0xb9, 0x17, 0x16, 0x0d, 0x1a, 0xbd, 0x14, 0x2a, 0xe7, 0x72,
0x7e, 0x86, 0x65, 0xe9, 0xd6, 0x09, 0xf9, 0xba, 0xd6, 0xf5, 0xe7, 0xa5, 0x7e, 0x07, 0x95, 0xe7,
0x94, 0x4f, 0x98, 0x5b, 0xba, 0x13, 0x30, 0x45, 0x9c, 0xeb, 0x00, 0x1c, 0xc2, 0x8a, 0xf4, 0x5a,
0x34, 0x99, 0x6b, 0x8e, 0x6f, 0x12, 0x14, 0x4a, 0xdc, 0xcd, 0x85, 0x8d, 0xc4, 0x5c, 0xa8, 0xa6,
0xae, 0x5f, 0x4d, 0x14, 0x52, 0xa8, 0xd9, 0x51, 0x9f, 0x02, 0x47, 0x7a, 0x08, 0x15, 0x69, 0x4b,
0x78, 0xd5, 0x6b, 0x7c, 0x17, 0x87, 0x84, 0x4a, 0xeb, 0x39, 0x90, 0xb1, 0x24, 0xb2, 0x9a, 0xae,
0x2a, 0xc8, 0x46, 0xfe, 0xfa, 0x43, 0x29, 0x3e, 0x38, 0x6f, 0xc1, 0x12, 0x4f, 0x22, 0x7e, 0x3d,
0x36, 0x33, 0x89, 0xf8, 0x88, 0x9c, 0x5b, 0xee, 0x00, 0x96, 0x43, 0x51, 0x45, 0xbc, 0x3e, 0xd3,
0xef, 0x09, 0xea, 0x3b, 0x79, 0xa0, 0xd1, 0x02, 0x82, 0x74, 0xa5, 0x54, 0xf4, 0xe9, 0xea, 0x9c,
0xc6, 0xef, 0xa0, 0x2a, 0xb5, 0xfd, 0x6b, 0x5e, 0x63, 0x7c, 0x02, 0xa3, 0x31, 0xde, 0x2f, 0xc8,
0x93, 0x48, 0x9e, 0xb8, 0xcd, 0x57, 0x92, 0xcf, 0x7d, 0x72, 0x5f, 0x17, 0xc3, 0xcc, 0x1f, 0x0f,
0xf5, 0x76, 0x5e, 0x78, 0x24, 0xf9, 0x1b, 0x2c, 0x04, 0x8f, 0xf0, 0x74, 0x22, 0x4e, 0x4d, 0x8e,
0xde, 0xff, 0xf5, 0xdb, 0x67, 0xe2, 0x22, 0x76, 0x0a, 0x6b, 0x6f, 0x46, 0x96, 0x2c, 0x02, 0x54,
0xa9, 0x11, 0x16, 0x3b, 0x69, 0x17, 0x4e, 0x0a, 0xaa, 0x24, 0x6e, 0x97, 0x0f, 0xce, 0x8a, 0x8e,
0x03, 0x57, 0x0d, 0x74, 0x90, 0x72, 0xec, 0xbc, 0x7a, 0xb1, 0x8b, 0x9c, 0xd3, 0x01, 0xf6, 0x84,
0x87, 0x74, 0x98, 0x2e, 0x82, 0xd4, 0x0f, 0x1f, 0x0d, 0x38, 0xe7, 0x5e, 0xf0, 0xe0, 0xcb, 0xae,
0x7b, 0x44, 0x1d, 0xdb, 0x4a, 0x54, 0x36, 0xbb, 0x28, 0xe8, 0x36, 0x35, 0x0f, 0x30, 0x5b, 0x33,
0x39, 0x25, 0x02, 0xe7, 0xd4, 0x34, 0x61, 0x2d, 0x38, 0xa9, 0x3f, 0x38, 0x63, 0x7e, 0x20, 0x6b,
0x4e, 0x07, 0x05, 0x5a, 0xe9, 0x4c, 0x67, 0x51, 0x41, 0xdb, 0x99, 0xc8, 0x1c, 0x6e, 0xec, 0x03,
0xec, 0xa0, 0xd8, 0x45, 0xe1, 0xd9, 0xa6, 0xee, 0x4e, 0x9e, 0x00, 0x34, 0x5b, 0x21, 0x03, 0x17,
0x6d, 0x85, 0x1e, 0xcc, 0xab, 0xbf, 0x1b, 0xa4, 0x99, 0x39, 0x29, 0xfc, 0x37, 0x33, 0xab, 0x16,
0x8d, 0xfe, 0xdf, 0xc4, 0xee, 0x1a, 0x79, 0x98, 0x26, 0x7f, 0x4d, 0x34, 0x77, 0x4d, 0x12, 0x34,
0xfb, 0xae, 0x49, 0x63, 0xe3, 0x77, 0xcd, 0x0b, 0x9b, 0x07, 0x83, 0xaf, 0x29, 0x3f, 0xd4, 0x55,
0x18, 0x29, 0xd4, 0xec, 0xbb, 0x66, 0x0a, 0x1c, 0xf3, 0x58, 0xc5, 0x40, 0x39, 0x10, 0xf8, 0x4d,
0xfb, 0xf0, 0x8b, 0xff, 0xd6, 0x3a, 0x2b, 0xce, 0x6f, 0xa3, 0xea, 0x3d, 0x7a, 0xa8, 0xa5, 0xd3,
0xe4, 0xe4, 0x30, 0x46, 0x10, 0xf9, 0xa6, 0xcc, 0xc1, 0x1c, 0x9c, 0xf5, 0xcf, 0xcd, 0xdc, 0x97,
0xb7, 0xa1, 0xdc, 0xc8, 0x31, 0x66, 0xdd, 0xc5, 0x9d, 0x84, 0xe5, 0xcf, 0xf0, 0x32, 0x0c, 0x72,
0xde, 0x1b, 0x8e, 0x1e, 0xd7, 0x64, 0xf8, 0x04, 0x66, 0xf6, 0xf5, 0x94, 0x82, 0xc6, 0xf6, 0xd0,
0x72, 0xe2, 0x91, 0x9c, 0x5e, 0xc7, 0x24, 0xa8, 0x59, 0x4f, 0xf6, 0xfa, 0xfd, 0x9c, 0xe8, 0xd8,
0x1e, 0x02, 0x15, 0x6e, 0x83, 0x39, 0xa8, 0x39, 0xd6, 0x13, 0x40, 0x4e, 0x77, 0xbd, 0x84, 0x45,
0x79, 0x87, 0xfa, 0x94, 0x37, 0xb5, 0x57, 0xec, 0x39, 0x08, 0xdf, 0x41, 0xf5, 0xe5, 0x08, 0x3d,
0x2a, 0x50, 0xfa, 0xcb, 0xe7, 0xcd, 0x3e, 0x59, 0x29, 0x54, 0xee, 0x37, 0x1f, 0xf4, 0x50, 0x66,
0xea, 0x19, 0x4e, 0x98, 0x00, 0x66, 0xe7, 0xb6, 0x38, 0x2e, 0xf6, 0x24, 0x0e, 0x04, 0xa4, 0x61,
0x33, 0x05, 0x7c, 0xcb, 0x73, 0x08, 0x28, 0x5c, 0xa2, 0xa6, 0x56, 0xc2, 0xc8, 0xd9, 0xd8, 0x33,
0x75, 0x79, 0x2e, 0x09, 0x3a, 0xa3, 0xa6, 0x4e, 0x61, 0xe3, 0x0f, 0xfc, 0xc0, 0xcf, 0x7b, 0x9e,
0x7d, 0x64, 0x3b, 0x38, 0x40, 0xcd, 0x71, 0x4b, 0xc3, 0x72, 0xc6, 0x63, 0x1f, 0xca, 0x4a, 0x7c,
0xc7, 0xa3, 0xae, 0x20, 0xb3, 0xfc, 0xe0, 0x23, 0x42, 0xda, 0xd6, 0xd9, 0xc0, 0x68, 0x11, 0x26,
0x80, 0x3c, 0x83, 0x7b, 0xcc, 0xb1, 0xcd, 0xd3, 0x74, 0x99, 0x1e, 0xe5, 0xa1, 0x09, 0x44, 0x53,
0xa6, 0x67, 0x22, 0x43, 0x91, 0xad, 0xc7, 0xbf, 0x3c, 0x1a, 0xd8, 0xe2, 0x60, 0xbc, 0x2f, 0x97,
0xb8, 0xa1, 0x26, 0xde, 0xb7, 0x59, 0xf0, 0xb5, 0x11, 0x4e, 0xde, 0xf0, 0xb9, 0x36, 0xa2, 0xd3,
0x3a, 0xda, 0xdf, 0x9f, 0xf7, 0xbb, 0x1e, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xb9, 0x19, 0xf1,
0xf3, 0xdc, 0x1a, 0x00, 0x00,
// 1621 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x5d, 0x73, 0xd3, 0x46,
0x17, 0xc6, 0x36, 0xf9, 0x3a, 0x76, 0xe2, 0xb0, 0x43, 0xc0, 0xaf, 0xe1, 0x6d, 0x8d, 0xa1, 0xe0,
0xf0, 0xe1, 0x30, 0x61, 0x86, 0x52, 0xee, 0x48, 0x4c, 0x83, 0xa7, 0x64, 0x08, 0x32, 0x74, 0xe8,
0x07, 0xe3, 0x6e, 0xac, 0x83, 0xa3, 0x89, 0xac, 0x35, 0xda, 0x75, 0x3e, 0x2e, 0x3b, 0xd3, 0xfb,
0xfe, 0xa7, 0xf6, 0xa7, 0xf4, 0x77, 0x74, 0xa6, 0xb3, 0x5a, 0x49, 0x96, 0x64, 0xad, 0xa2, 0x00,
0x77, 0xda, 0xdd, 0x67, 0x9f, 0xe7, 0xec, 0x39, 0xbb, 0x67, 0xcf, 0x0a, 0x56, 0x5d, 0xc6, 0x44,
0x7f, 0xc0, 0x98, 0x6b, 0xb6, 0xc7, 0x2e, 0x13, 0x8c, 0x5c, 0x19, 0x59, 0xf6, 0xd1, 0x84, 0xab,
0x56, 0x5b, 0x0e, 0x7b, 0xa3, 0xf5, 0xca, 0x80, 0x8d, 0x46, 0xcc, 0x51, 0xfd, 0xf5, 0x4a, 0x14,
0x55, 0x5f, 0xb1, 0x1c, 0x81, 0xae, 0x43, 0x6d, 0xbf, 0x5d, 0x1e, 0xbb, 0xec, 0xe4, 0xd4, 0x6f,
0xac, 0x9a, 0x54, 0xd0, 0xa8, 0x44, 0xbd, 0x8a, 0x62, 0x60, 0xf6, 0x47, 0x28, 0xa8, 0xdf, 0x71,
0xc9, 0x72, 0x4c, 0x3c, 0x89, 0x62, 0x9a, 0x7d, 0x58, 0x7b, 0x66, 0xdb, 0x6c, 0xf0, 0xc6, 0x1a,
0x21, 0x17, 0x74, 0x34, 0x36, 0xf0, 0xe3, 0x04, 0xb9, 0x20, 0x0f, 0xe1, 0xe2, 0x3e, 0xe5, 0x58,
0x2b, 0x34, 0x0a, 0xad, 0xf2, 0xe6, 0xf5, 0x76, 0xcc, 0x5c, 0xdf, 0xc6, 0x5d, 0x3e, 0xdc, 0xa2,
0x1c, 0x0d, 0x0f, 0x49, 0x2e, 0xc3, 0xdc, 0x80, 0x4d, 0x1c, 0x51, 0x2b, 0x35, 0x0a, 0xad, 0x65,
0x43, 0x35, 0x9a, 0xbf, 0x17, 0xe0, 0x4a, 0x52, 0x81, 0x8f, 0x99, 0xc3, 0x91, 0x3c, 0x82, 0x79,
0x2e, 0xa8, 0x98, 0x70, 0x5f, 0xe4, 0x5a, 0xaa, 0x48, 0xcf, 0x83, 0x18, 0x3e, 0x94, 0x5c, 0x87,
0x25, 0x11, 0x30, 0xd5, 0x8a, 0x8d, 0x42, 0xeb, 0xa2, 0x31, 0xed, 0xd0, 0xd8, 0xf0, 0x0e, 0x56,
0x3c, 0x13, 0xba, 0x9d, 0x2f, 0xb0, 0xba, 0x62, 0x94, 0xd9, 0x86, 0x6a, 0xc8, 0xfc, 0x39, 0xab,
0x5a, 0x81, 0x62, 0xb7, 0xe3, 0x51, 0x97, 0x8c, 0x62, 0xb7, 0xa3, 0x59, 0xc7, 0x5f, 0x45, 0xa8,
0x74, 0x47, 0x63, 0xe6, 0x0a, 0x03, 0xf9, 0xc4, 0x16, 0x9f, 0xa6, 0x75, 0x15, 0x16, 0x04, 0xe5,
0x87, 0x7d, 0xcb, 0xf4, 0x05, 0xe7, 0x65, 0xb3, 0x6b, 0x92, 0xaf, 0xa1, 0x2c, 0xf7, 0x90, 0xc3,
0x4c, 0x94, 0x83, 0x25, 0x6f, 0x10, 0x82, 0xae, 0xae, 0x49, 0x1e, 0xc3, 0x9c, 0xe4, 0xc0, 0xda,
0xc5, 0x46, 0xa1, 0xb5, 0xb2, 0xd9, 0x48, 0x55, 0x53, 0x06, 0x4a, 0x4d, 0x34, 0x14, 0x9c, 0xd4,
0x61, 0x91, 0xe3, 0x70, 0x84, 0x8e, 0xe0, 0xb5, 0xb9, 0x46, 0xa9, 0x55, 0x32, 0xc2, 0x36, 0xf9,
0x1f, 0x2c, 0xd2, 0x89, 0x60, 0x7d, 0xcb, 0xe4, 0xb5, 0x79, 0x6f, 0x6c, 0x41, 0xb6, 0xbb, 0x26,
0x27, 0xd7, 0x60, 0xc9, 0x65, 0xc7, 0x7d, 0xe5, 0x88, 0x05, 0xcf, 0x9a, 0x45, 0x97, 0x1d, 0x6f,
0xcb, 0x36, 0xf9, 0x16, 0xe6, 0x2c, 0xe7, 0x03, 0xe3, 0xb5, 0xc5, 0x46, 0xa9, 0x55, 0xde, 0xbc,
0x91, 0x6a, 0xcb, 0x0f, 0x78, 0xfa, 0x23, 0xb5, 0x27, 0xb8, 0x47, 0x2d, 0xd7, 0x50, 0xf8, 0xe6,
0x9f, 0x05, 0xb8, 0xda, 0x41, 0x3e, 0x70, 0xad, 0x7d, 0xec, 0xf9, 0x56, 0x7c, 0xfa, 0xb6, 0x68,
0x42, 0x65, 0xc0, 0x6c, 0x1b, 0x07, 0xc2, 0x62, 0x4e, 0x18, 0xc2, 0x58, 0x1f, 0xf9, 0x0a, 0xc0,
0x5f, 0x6e, 0xb7, 0xc3, 0x6b, 0x25, 0x6f, 0x91, 0x91, 0x9e, 0xe6, 0x04, 0xaa, 0xbe, 0x21, 0x92,
0xb8, 0xeb, 0x7c, 0x60, 0x33, 0xb4, 0x85, 0x14, 0xda, 0x06, 0x94, 0xc7, 0xd4, 0x15, 0x56, 0x4c,
0x39, 0xda, 0x25, 0xcf, 0x4a, 0x28, 0xe3, 0x87, 0x73, 0xda, 0xd1, 0xfc, 0xa7, 0x08, 0x15, 0x5f,
0x57, 0x6a, 0x72, 0xd2, 0x81, 0x25, 0xb9, 0xa6, 0xbe, 0xf4, 0x93, 0xef, 0x82, 0x3b, 0xed, 0xf4,
0x34, 0xd5, 0x4e, 0x18, 0x6c, 0x2c, 0xee, 0x07, 0xa6, 0x77, 0xa0, 0xac, 0xd2, 0x8c, 0x0a, 0x4f,
0xd1, 0x0b, 0xcf, 0xcd, 0x38, 0x8f, 0x4c, 0x4c, 0xed, 0x50, 0xdb, 0xc4, 0x13, 0x8f, 0x03, 0xac,
0xe0, 0x93, 0x13, 0x84, 0x4b, 0x78, 0x22, 0x5c, 0xda, 0x8f, 0x72, 0x95, 0x3c, 0xae, 0xef, 0xce,
0xb0, 0xc9, 0x23, 0x68, 0x3f, 0x97, 0xb3, 0x43, 0x6e, 0xfe, 0xdc, 0x11, 0xee, 0xa9, 0x51, 0xc5,
0x78, 0x6f, 0xfd, 0x37, 0xb8, 0x9c, 0x06, 0x24, 0xab, 0x50, 0x3a, 0xc4, 0x53, 0xdf, 0xed, 0xf2,
0x93, 0x6c, 0xc2, 0xdc, 0x91, 0xdc, 0x4a, 0x9e, 0x9f, 0x67, 0xf6, 0x86, 0xb7, 0xa0, 0xe9, 0x4a,
0x14, 0xf4, 0x69, 0xf1, 0x49, 0xa1, 0xf9, 0x77, 0x11, 0x6a, 0xb3, 0xdb, 0xed, 0x73, 0x72, 0x45,
0x9e, 0x2d, 0x37, 0x84, 0x65, 0x3f, 0xd0, 0x31, 0xd7, 0x6d, 0xe9, 0x5c, 0xa7, 0xb3, 0x30, 0xe6,
0x53, 0xe5, 0xc3, 0x0a, 0x8f, 0x74, 0xd5, 0x11, 0x2e, 0xcd, 0x40, 0x52, 0xbc, 0xf7, 0x34, 0xee,
0xbd, 0x5b, 0x79, 0x42, 0x18, 0xf5, 0xa2, 0x09, 0x97, 0x77, 0x50, 0x6c, 0xbb, 0x68, 0xa2, 0x23,
0x2c, 0x6a, 0x7f, 0xfa, 0x81, 0xad, 0xc3, 0xe2, 0x84, 0xcb, 0x4b, 0x74, 0xa4, 0x8c, 0x59, 0x32,
0xc2, 0x76, 0xf3, 0x8f, 0x02, 0xac, 0x25, 0x64, 0x3e, 0x27, 0x50, 0x19, 0x52, 0x72, 0x6c, 0x4c,
0x39, 0x3f, 0x66, 0xae, 0x4a, 0xb4, 0x4b, 0x46, 0xd8, 0xde, 0xfc, 0xf7, 0x26, 0x2c, 0x19, 0x8c,
0x89, 0x6d, 0xe9, 0x12, 0x32, 0x06, 0x22, 0x6d, 0x62, 0xa3, 0x31, 0x73, 0xd0, 0x51, 0x89, 0x95,
0x93, 0x87, 0x71, 0x03, 0xc2, 0xc2, 0x60, 0x16, 0xea, 0xbb, 0xaa, 0x7e, 0x5b, 0x33, 0x23, 0x01,
0x6f, 0x5e, 0x20, 0x23, 0x4f, 0x51, 0xde, 0xd7, 0x6f, 0xac, 0xc1, 0xe1, 0xf6, 0x01, 0x75, 0x1c,
0xb4, 0xb3, 0x14, 0x13, 0xd0, 0x40, 0x31, 0x71, 0xe8, 0xfd, 0x46, 0x4f, 0xb8, 0x96, 0x33, 0x0c,
0x3c, 0xdb, 0xbc, 0x40, 0x3e, 0x7a, 0xb1, 0x95, 0xea, 0x16, 0x17, 0xd6, 0x80, 0x07, 0x82, 0x9b,
0x7a, 0xc1, 0x19, 0xf0, 0x39, 0x25, 0xfb, 0xb0, 0xba, 0xed, 0x22, 0x15, 0xb8, 0x1d, 0x1e, 0x1a,
0x72, 0x3f, 0x75, 0x6a, 0x12, 0x16, 0x08, 0x65, 0x6d, 0x80, 0xe6, 0x05, 0xf2, 0x0b, 0xac, 0x74,
0x5c, 0x36, 0x8e, 0xd0, 0xdf, 0x4d, 0xa5, 0x8f, 0x83, 0x72, 0x92, 0xf7, 0x61, 0xf9, 0x05, 0xe5,
0x11, 0xee, 0xf5, 0x54, 0xee, 0x18, 0x26, 0xa0, 0xbe, 0x91, 0x0a, 0xdd, 0x62, 0xcc, 0x8e, 0xb8,
0xe7, 0x18, 0x48, 0x90, 0x10, 0x22, 0x2a, 0xed, 0xf4, 0x15, 0xcc, 0x00, 0x03, 0xa9, 0x8d, 0xdc,
0xf8, 0x50, 0xf8, 0x2d, 0x94, 0x95, 0xc3, 0x9f, 0xd9, 0x16, 0xe5, 0xe4, 0x4e, 0x46, 0x48, 0x3c,
0x44, 0x4e, 0x87, 0xbd, 0x86, 0x25, 0xe9, 0x68, 0x45, 0xfa, 0x8d, 0x36, 0x10, 0xe7, 0xa1, 0xec,
0x01, 0x3c, 0xb3, 0x05, 0xba, 0x8a, 0xf3, 0x76, 0x2a, 0xe7, 0x14, 0x90, 0x93, 0xd4, 0x81, 0x6a,
0xef, 0x40, 0x16, 0x38, 0x81, 0x6b, 0x38, 0xb9, 0x97, 0xbe, 0xa1, 0xe3, 0xa8, 0x80, 0xfe, 0x7e,
0x3e, 0x70, 0xe8, 0xee, 0xf7, 0x50, 0x55, 0xce, 0xdc, 0x0b, 0x8a, 0x06, 0x8d, 0x5e, 0x02, 0x95,
0x73, 0x39, 0x3f, 0xc1, 0xb2, 0x74, 0xeb, 0x94, 0x7c, 0x5d, 0xeb, 0xfa, 0xf3, 0x52, 0xbf, 0x87,
0xca, 0x0b, 0xca, 0xa7, 0xcc, 0x2d, 0xdd, 0x09, 0x98, 0x21, 0xce, 0x75, 0x00, 0x0e, 0x61, 0x45,
0x7a, 0x2d, 0x9c, 0xcc, 0x35, 0xc7, 0x37, 0x0e, 0x0a, 0x24, 0xee, 0xe5, 0xc2, 0x86, 0x62, 0x0e,
0x54, 0x13, 0xd7, 0xaf, 0x26, 0x0a, 0x09, 0x54, 0x76, 0xd4, 0x67, 0xc0, 0xa1, 0x1e, 0x42, 0x45,
0xda, 0x12, 0x5c, 0xf5, 0x1a, 0xdf, 0x45, 0x21, 0x81, 0xd2, 0x7a, 0x0e, 0x64, 0x24, 0x89, 0xac,
0x26, 0xab, 0x0a, 0xb2, 0x91, 0xbf, 0xfe, 0x50, 0x8a, 0x0f, 0xcf, 0x5b, 0xb0, 0x44, 0x93, 0x88,
0x57, 0x8f, 0x65, 0x26, 0x11, 0x0f, 0x91, 0x73, 0xcb, 0x1d, 0xc0, 0x72, 0x20, 0xaa, 0x88, 0xd7,
0x33, 0xfd, 0x1e, 0xa3, 0xbe, 0x9b, 0x07, 0x1a, 0x2e, 0xc0, 0x4f, 0x57, 0x4a, 0x45, 0x9f, 0xae,
0xce, 0x69, 0xfc, 0x0e, 0xaa, 0x52, 0xdb, 0xbb, 0xe6, 0x35, 0xc6, 0xc7, 0x30, 0x1a, 0xe3, 0xbd,
0x82, 0x3c, 0x8e, 0xe4, 0xb1, 0xdb, 0x7c, 0x25, 0xfe, 0xdc, 0x27, 0x0f, 0x74, 0x31, 0x4c, 0xfd,
0xf1, 0x50, 0x6f, 0xe7, 0x85, 0x87, 0x92, 0xbf, 0xc2, 0x82, 0xff, 0x08, 0x4f, 0x26, 0xe2, 0xc4,
0xe4, 0xf0, 0xfd, 0x5f, 0xbf, 0x73, 0x26, 0x2e, 0x64, 0xa7, 0xb0, 0xf6, 0x76, 0x6c, 0xca, 0x22,
0x40, 0x95, 0x1a, 0x41, 0xb1, 0x93, 0x74, 0xe1, 0xb4, 0xa0, 0x8a, 0xe3, 0x76, 0xf9, 0xf0, 0xac,
0xe8, 0xd8, 0x70, 0xd5, 0x40, 0x1b, 0x29, 0xc7, 0xce, 0xeb, 0x97, 0xbb, 0xc8, 0x39, 0x1d, 0x62,
0x4f, 0xb8, 0x48, 0x47, 0xc9, 0x22, 0x48, 0xfd, 0xf0, 0xd1, 0x80, 0x73, 0xee, 0x05, 0x17, 0xfe,
0xdf, 0x75, 0x8e, 0xa8, 0x6d, 0x99, 0xb1, 0xca, 0x66, 0x17, 0x05, 0xdd, 0xa6, 0x83, 0x03, 0x4c,
0xd7, 0x8c, 0x4f, 0x09, 0xc1, 0x39, 0x35, 0x07, 0xb0, 0xe6, 0x9f, 0xd4, 0xef, 0xed, 0x09, 0x3f,
0x90, 0x35, 0xa7, 0x8d, 0x02, 0xcd, 0x64, 0xa6, 0x33, 0xa9, 0xa0, 0xed, 0x54, 0x64, 0x0e, 0x37,
0xf6, 0x01, 0x76, 0x50, 0xec, 0xa2, 0x70, 0xad, 0x81, 0xee, 0x4e, 0x9e, 0x02, 0x34, 0x5b, 0x21,
0x05, 0x17, 0x6e, 0x85, 0x1e, 0xcc, 0xab, 0xbf, 0x1b, 0xa4, 0x99, 0x3a, 0x29, 0xf8, 0x37, 0x93,
0x55, 0x8b, 0x86, 0xff, 0x6f, 0x22, 0x77, 0x8d, 0x3c, 0x4c, 0xd3, 0xbf, 0x26, 0x9a, 0xbb, 0x26,
0x0e, 0xca, 0xbe, 0x6b, 0x92, 0xd8, 0xe8, 0x5d, 0xf3, 0xd2, 0xe2, 0xfe, 0xe0, 0x1b, 0xca, 0x0f,
0x75, 0x15, 0x46, 0x02, 0x95, 0x7d, 0xd7, 0xcc, 0x80, 0x23, 0x1e, 0xab, 0x18, 0x28, 0x07, 0x7c,
0xbf, 0x69, 0x1f, 0x7e, 0xd1, 0xdf, 0x5a, 0x67, 0xc5, 0xf9, 0x5d, 0x58, 0xbd, 0x87, 0x0f, 0xb5,
0x64, 0x9a, 0x9c, 0x1e, 0xc6, 0x10, 0x22, 0xdf, 0x94, 0x39, 0x98, 0xfd, 0xb3, 0xfe, 0xa5, 0x99,
0xfb, 0xf2, 0x36, 0x94, 0x1b, 0x39, 0xc2, 0xac, 0xbb, 0xb8, 0xe3, 0xb0, 0xfc, 0x19, 0x5e, 0x86,
0x41, 0xce, 0x7b, 0xcb, 0xd1, 0xe5, 0x9a, 0x0c, 0x1f, 0xc3, 0x64, 0x5f, 0x4f, 0x09, 0x68, 0x64,
0x0f, 0x2d, 0xc7, 0x1e, 0xc9, 0xc9, 0x75, 0x4c, 0x83, 0x9a, 0xf6, 0x64, 0xaf, 0x3f, 0xc8, 0x89,
0x8e, 0xec, 0x21, 0x50, 0xe1, 0x36, 0x98, 0x8d, 0x9a, 0x63, 0x3d, 0x05, 0xe4, 0x74, 0xd7, 0x2b,
0x58, 0x94, 0x77, 0xa8, 0x47, 0x79, 0x4b, 0x7b, 0xc5, 0x9e, 0x83, 0xf0, 0x3d, 0x54, 0x5f, 0x8d,
0xd1, 0xa5, 0x02, 0xa5, 0xbf, 0x3c, 0xde, 0xf4, 0x93, 0x95, 0x40, 0xe5, 0x7e, 0xf3, 0x41, 0x0f,
0x65, 0xa6, 0xce, 0x70, 0xc2, 0x14, 0x90, 0x9d, 0xdb, 0xa2, 0xb8, 0xc8, 0x93, 0xd8, 0x17, 0x90,
0x86, 0x65, 0x0a, 0x78, 0x96, 0xe7, 0x10, 0x50, 0xb8, 0xe8, 0x9b, 0xdb, 0x5f, 0xfa, 0x9e, 0x6b,
0x1d, 0x59, 0x36, 0x0e, 0x51, 0x73, 0x02, 0x92, 0xb0, 0x9c, 0x2e, 0xda, 0x87, 0xb2, 0x12, 0xde,
0x71, 0xa9, 0x23, 0x48, 0x96, 0x69, 0x1e, 0x22, 0xa0, 0x6d, 0x9d, 0x0d, 0x0c, 0x17, 0x31, 0x00,
0x90, 0xc7, 0x62, 0x8f, 0xd9, 0xd6, 0xe0, 0x34, 0x59, 0x39, 0x87, 0xa9, 0x61, 0x0a, 0xd1, 0x54,
0xce, 0xa9, 0xc8, 0x40, 0x64, 0xeb, 0xc9, 0xcf, 0x8f, 0x87, 0x96, 0x38, 0x98, 0xec, 0xcb, 0x25,
0x6e, 0xa8, 0x89, 0x0f, 0x2c, 0xe6, 0x7f, 0x6d, 0x04, 0x93, 0x37, 0x3c, 0xae, 0x8d, 0xf0, 0x00,
0x8d, 0xf7, 0xf7, 0xe7, 0xbd, 0xae, 0x47, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x94, 0xcd,
0x4d, 0x6f, 0x1a, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -888,7 +887,6 @@ type RootCoordClient interface {
OperateUserRole(ctx context.Context, in *milvuspb.OperateUserRoleRequest, opts ...grpc.CallOption) (*commonpb.Status, error)
SelectRole(ctx context.Context, in *milvuspb.SelectRoleRequest, opts ...grpc.CallOption) (*milvuspb.SelectRoleResponse, error)
SelectUser(ctx context.Context, in *milvuspb.SelectUserRequest, opts ...grpc.CallOption) (*milvuspb.SelectUserResponse, error)
SelectResource(ctx context.Context, in *milvuspb.SelectResourceRequest, opts ...grpc.CallOption) (*milvuspb.SelectResourceResponse, error)
OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error)
SelectGrant(ctx context.Context, in *milvuspb.SelectGrantRequest, opts ...grpc.CallOption) (*milvuspb.SelectGrantResponse, error)
ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest, opts ...grpc.CallOption) (*internalpb.ListPolicyResponse, error)
@ -1289,15 +1287,6 @@ func (c *rootCoordClient) SelectUser(ctx context.Context, in *milvuspb.SelectUse
return out, nil
}
func (c *rootCoordClient) SelectResource(ctx context.Context, in *milvuspb.SelectResourceRequest, opts ...grpc.CallOption) (*milvuspb.SelectResourceResponse, error) {
out := new(milvuspb.SelectResourceResponse)
err := c.cc.Invoke(ctx, "/milvus.proto.rootcoord.RootCoord/SelectResource", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *rootCoordClient) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
out := new(commonpb.Status)
err := c.cc.Invoke(ctx, "/milvus.proto.rootcoord.RootCoord/OperatePrivilege", in, out, opts...)
@ -1421,7 +1410,6 @@ type RootCoordServer interface {
OperateUserRole(context.Context, *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error)
SelectRole(context.Context, *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error)
SelectUser(context.Context, *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error)
SelectResource(context.Context, *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error)
OperatePrivilege(context.Context, *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error)
SelectGrant(context.Context, *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error)
ListPolicy(context.Context, *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error)
@ -1560,9 +1548,6 @@ func (*UnimplementedRootCoordServer) SelectRole(ctx context.Context, req *milvus
func (*UnimplementedRootCoordServer) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SelectUser not implemented")
}
func (*UnimplementedRootCoordServer) SelectResource(ctx context.Context, req *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SelectResource not implemented")
}
func (*UnimplementedRootCoordServer) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return nil, status.Errorf(codes.Unimplemented, "method OperatePrivilege not implemented")
}
@ -2351,24 +2336,6 @@ func _RootCoord_SelectUser_Handler(srv interface{}, ctx context.Context, dec fun
return interceptor(ctx, in, info, handler)
}
func _RootCoord_SelectResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(milvuspb.SelectResourceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RootCoordServer).SelectResource(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/milvus.proto.rootcoord.RootCoord/SelectResource",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RootCoordServer).SelectResource(ctx, req.(*milvuspb.SelectResourceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RootCoord_OperatePrivilege_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(milvuspb.OperatePrivilegeRequest)
if err := dec(in); err != nil {
@ -2599,10 +2566,6 @@ var _RootCoord_serviceDesc = grpc.ServiceDesc{
MethodName: "SelectUser",
Handler: _RootCoord_SelectUser_Handler,
},
{
MethodName: "SelectResource",
Handler: _RootCoord_SelectResource_Handler,
},
{
MethodName: "OperatePrivilege",
Handler: _RootCoord_OperatePrivilege_Handler,

View File

@ -25,7 +25,7 @@ func TestValidAuth(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
res = validAuth(ctx, []string{crypto.Base64Encode("mockUser:mockPass")})
assert.True(t, res)
@ -54,7 +54,7 @@ func TestAuthenticationInterceptor(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err = InitMetaCache(rootCoord, queryCoord, mgr)
err = InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
// with invalid metadata
md := metadata.Pairs("xxx", "yyy")

View File

@ -23,6 +23,8 @@ import (
"os"
"strconv"
"github.com/milvus-io/milvus/internal/util/errorutil"
"github.com/milvus-io/milvus/internal/util"
"go.uber.org/zap"
@ -3705,6 +3707,11 @@ func (node *Proxy) checkHealthy() bool {
return code == internalpb.StateCode_Healthy
}
func (node *Proxy) checkHealthyAndReturnCode() (internalpb.StateCode, bool) {
code := node.stateCode.Load().(internalpb.StateCode)
return code, code == internalpb.StateCode_Healthy
}
//unhealthyStatus returns the proxy not healthy status
func unhealthyStatus() *commonpb.Status {
return &commonpb.Status{
@ -3816,6 +3823,9 @@ func (node *Proxy) InvalidateCredentialCache(ctx context.Context, request *proxy
logutil.Logger(ctx).Debug("received request to invalidate credential cache",
zap.String("role", typeutil.ProxyRole),
zap.String("username", request.Username))
if !node.checkHealthy() {
return unhealthyStatus(), errorutil.UnhealthyError()
}
username := request.Username
if globalMetaCache != nil {
@ -3837,6 +3847,9 @@ func (node *Proxy) UpdateCredentialCache(ctx context.Context, request *proxypb.U
logutil.Logger(ctx).Debug("received request to update credential cache",
zap.String("role", typeutil.ProxyRole),
zap.String("username", request.Username))
if !node.checkHealthy() {
return unhealthyStatus(), errorutil.UnhealthyError()
}
credInfo := &internalpb.CredentialInfo{
Username: request.Username,
@ -3856,7 +3869,14 @@ func (node *Proxy) UpdateCredentialCache(ctx context.Context, request *proxypb.U
}
func (node *Proxy) CreateCredential(ctx context.Context, req *milvuspb.CreateCredentialRequest) (*commonpb.Status, error) {
log.Debug("CreateCredential", zap.String("role", typeutil.RootCoordRole), zap.String("username", req.Username))
log.Debug("CreateCredential", zap.String("role", typeutil.ProxyRole), zap.String("username", req.Username))
if !node.checkHealthy() {
return unhealthyStatus(), errorutil.UnhealthyError()
}
// validate root permission
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
// validate params
username := req.Username
if err := ValidateUsername(username); err != nil {
@ -3888,6 +3908,7 @@ func (node *Proxy) CreateCredential(ctx context.Context, req *milvuspb.CreateCre
Reason: "encrypt password fail key:" + req.Username,
}, nil
}
credInfo := &internalpb.CredentialInfo{
Username: req.Username,
EncryptedPassword: encryptedPassword,
@ -3905,7 +3926,10 @@ func (node *Proxy) CreateCredential(ctx context.Context, req *milvuspb.CreateCre
}
func (node *Proxy) UpdateCredential(ctx context.Context, req *milvuspb.UpdateCredentialRequest) (*commonpb.Status, error) {
log.Debug("UpdateCredential", zap.String("role", typeutil.RootCoordRole), zap.String("username", req.Username))
log.Debug("UpdateCredential", zap.String("role", typeutil.ProxyRole), zap.String("username", req.Username))
if !node.checkHealthy() {
return unhealthyStatus(), errorutil.UnhealthyError()
}
rawOldPassword, err := crypto.Base64Decode(req.OldPassword)
if err != nil {
log.Error("decode old password fail", zap.String("username", req.Username), zap.Error(err))
@ -3971,7 +3995,15 @@ func (node *Proxy) UpdateCredential(ctx context.Context, req *milvuspb.UpdateCre
}
func (node *Proxy) DeleteCredential(ctx context.Context, req *milvuspb.DeleteCredentialRequest) (*commonpb.Status, error) {
log.Debug("DeleteCredential", zap.String("role", typeutil.RootCoordRole), zap.String("username", req.Username))
log.Debug("DeleteCredential", zap.String("role", typeutil.ProxyRole), zap.String("username", req.Username))
if !node.checkHealthy() {
return unhealthyStatus(), errorutil.UnhealthyError()
}
// validate root permission
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
if req.Username == util.UserRoot {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_DeleteCredentialFailure,
@ -3990,7 +4022,10 @@ func (node *Proxy) DeleteCredential(ctx context.Context, req *milvuspb.DeleteCre
}
func (node *Proxy) ListCredUsers(ctx context.Context, req *milvuspb.ListCredUsersRequest) (*milvuspb.ListCredUsersResponse, error) {
log.Debug("ListCredUsers", zap.String("role", typeutil.RootCoordRole))
log.Debug("ListCredUsers", zap.String("role", typeutil.ProxyRole))
if !node.checkHealthy() {
return &milvuspb.ListCredUsersResponse{Status: unhealthyStatus()}, errorutil.UnhealthyError()
}
rootCoordReq := &milvuspb.ListCredUsersRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_ListCredUsernames,
@ -4029,47 +4064,334 @@ func (node *Proxy) SendRetrieveResult(ctx context.Context, req *internalpb.Retri
}, nil
}
func (node *Proxy) CreateRole(ctx context.Context, request *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) validateAdminPermission(ctx context.Context) (bool, *commonpb.Status) {
err := ValidateAdminPermission(ctx)
if err != nil {
logger.Error("fail to validate admin permission", zap.Error(err))
return false, &commonpb.Status{
ErrorCode: commonpb.ErrorCode_PermissionDenied,
Reason: err.Error(),
}
}
return true, nil
}
func (node *Proxy) DropRole(ctx context.Context, request *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
logger.Debug("CreateRole", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
var roleName string
if req.Entity != nil {
roleName = req.Entity.Name
}
if err := ValidateRoleName(roleName); err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
}, err
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
result, err := node.rootCoord.CreateRole(ctx, req)
if err != nil {
logger.Error("fail to create role", zap.Error(err))
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
}, err
}
return result, nil
}
func (node *Proxy) OperateUserRole(ctx context.Context, request *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
logger.Debug("DropRole", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if err := ValidateRoleName(req.RoleName); err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
}, err
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
result, err := node.rootCoord.DropRole(ctx, req)
if err != nil {
logger.Error("fail to drop role", zap.String("role_name", req.RoleName), zap.Error(err))
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
}, err
}
return result, nil
}
func (node *Proxy) SelectRole(ctx context.Context, request *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
logger.Debug("OperateUserRole", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if err := ValidateUsername(req.Username); err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
}, err
}
if err := ValidateRoleName(req.RoleName); err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
}, err
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
result, err := node.rootCoord.OperateUserRole(ctx, req)
if err != nil {
logger.Error("fail to operate user role", zap.Error(err))
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
}, err
}
return result, nil
}
func (node *Proxy) SelectUser(ctx context.Context, request *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
logger.Debug("SelectRole", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return &milvuspb.SelectRoleResponse{Status: errorutil.UnhealthyStatus(code)}, errorutil.UnhealthyError()
}
if req.Role != nil {
if err := ValidateRoleName(req.Role.Name); err != nil {
return &milvuspb.SelectRoleResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
},
}, err
}
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return &milvuspb.SelectRoleResponse{
Status: status,
}, errorutil.PermissionDenyError()
}
result, err := node.rootCoord.SelectRole(ctx, req)
if err != nil {
logger.Error("fail to select role", zap.Error(err))
return &milvuspb.SelectRoleResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
},
}, err
}
return result, nil
}
func (node *Proxy) SelectResource(ctx context.Context, request *milvuspb.SelectResourceRequest) (*milvuspb.SelectResourceResponse, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
logger.Debug("SelectUser", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return &milvuspb.SelectUserResponse{Status: errorutil.UnhealthyStatus(code)}, errorutil.UnhealthyError()
}
if req.User != nil {
if err := ValidateUsername(req.User.Name); err != nil {
return &milvuspb.SelectUserResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
},
}, err
}
}
curUser, err := GetCurUserFromContext(ctx)
if err != nil {
return &milvuspb.SelectUserResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
},
}, err
}
isSelf := req.User != nil && req.User.Name == curUser
if isValid, status := node.validateAdminPermission(ctx); !isValid && !isSelf {
return &milvuspb.SelectUserResponse{
Status: status,
}, errorutil.PermissionDenyError()
}
result, err := node.rootCoord.SelectUser(ctx, req)
if err != nil {
logger.Error("fail to select user", zap.Error(err))
return &milvuspb.SelectUserResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
},
}, err
}
return result, nil
}
func (node *Proxy) OperatePrivilege(ctx context.Context, request *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) validPrivilegeParams(req *milvuspb.OperatePrivilegeRequest) error {
if req.Entity == nil {
return fmt.Errorf("the entity in the request is nil")
}
if req.Entity.Grantor == nil {
return fmt.Errorf("the grantor entity in the grant entity is nil")
}
if req.Entity.Grantor.Privilege == nil {
return fmt.Errorf("the privilege entity in the grantor entity is nil")
}
if err := ValidatePrivilege(req.Entity.Grantor.Privilege.Name); err != nil {
return err
}
if req.Entity.Object == nil {
return fmt.Errorf("the resource entity in the grant entity is nil")
}
if err := ValidateObjectType(req.Entity.Object.Name); err != nil {
return err
}
if err := ValidateObjectName(req.Entity.ObjectName); err != nil {
return err
}
if req.Entity.Role == nil {
return fmt.Errorf("the object entity in the grant entity is nil")
}
if err := ValidateRoleName(req.Entity.Role.Name); err != nil {
return err
}
return nil
}
func (node *Proxy) SelectGrant(ctx context.Context, request *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
logger.Debug("OperatePrivilege", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return status, errorutil.PermissionDenyError()
}
if err := node.validPrivilegeParams(req); err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
}, err
}
curUser, err := GetCurUserFromContext(ctx)
if err != nil {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
}, err
}
req.Entity.Grantor.User = &milvuspb.UserEntity{Name: curUser}
result, err := node.rootCoord.OperatePrivilege(ctx, req)
if err != nil {
logger.Error("fail to operate privilege", zap.Error(err))
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
}, err
}
return result, nil
}
func (node *Proxy) RefreshPolicyInfoCache(ctx context.Context, request *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
//TODO implement me
panic("implement me")
func (node *Proxy) validGrantParams(req *milvuspb.SelectGrantRequest) error {
if req.Entity == nil {
return fmt.Errorf("the grant entity in the request is nil")
}
if req.Entity.Object != nil {
if err := ValidateObjectType(req.Entity.Object.Name); err != nil {
return err
}
if err := ValidateObjectName(req.Entity.ObjectName); err != nil {
return err
}
}
if req.Entity.Role == nil {
return fmt.Errorf("the role entity in the grant entity is nil")
}
if err := ValidateRoleName(req.Entity.Role.Name); err != nil {
return err
}
return nil
}
func (node *Proxy) SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
logger.Debug("SelectGrant", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return &milvuspb.SelectGrantResponse{Status: errorutil.UnhealthyStatus(code)}, errorutil.UnhealthyError()
}
if isValid, status := node.validateAdminPermission(ctx); !isValid {
return &milvuspb.SelectGrantResponse{
Status: status,
}, errorutil.PermissionDenyError()
}
if err := node.validGrantParams(req); err != nil {
return &milvuspb.SelectGrantResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_IllegalArgument,
Reason: err.Error(),
},
}, err
}
result, err := node.rootCoord.SelectGrant(ctx, req)
if err != nil {
logger.Error("fail to select grant", zap.Error(err))
return &milvuspb.SelectGrantResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: err.Error(),
},
}, err
}
return result, nil
}
func (node *Proxy) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
logger.Debug("RefreshPrivilegeInfoCache", zap.Any("req", req))
if code, ok := node.checkHealthyAndReturnCode(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if globalMetaCache != nil {
err := globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{
OpType: typeutil.CacheOpType(req.OpType),
OpKey: req.OpKey,
})
if err != nil {
log.Error("fail to refresh policy info", zap.Error(err))
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_RefreshPolicyInfoCacheFailure,
Reason: err.Error(),
}, err
}
}
logger.Debug("RefreshPrivilegeInfoCache success")
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
}, nil
}

View File

@ -24,6 +24,8 @@ import (
"sync"
"time"
"github.com/milvus-io/milvus/internal/util/funcutil"
"go.uber.org/zap"
"github.com/milvus-io/milvus/internal/common"
@ -36,6 +38,7 @@ import (
"github.com/milvus-io/milvus/internal/proto/rootcoordpb"
"github.com/milvus-io/milvus/internal/proto/schemapb"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/retry"
"github.com/milvus-io/milvus/internal/util/timerecord"
"github.com/milvus-io/milvus/internal/util/typeutil"
@ -65,6 +68,11 @@ type Cache interface {
GetCredentialInfo(ctx context.Context, username string) (*internalpb.CredentialInfo, error)
RemoveCredential(username string)
UpdateCredential(credInfo *internalpb.CredentialInfo)
GetPrivilegeInfo(ctx context.Context) []string
GetUserRole(username string) []string
RefreshPolicyInfo(op typeutil.CacheOp) error
InitPolicyInfo(info []string, userRoles []string)
}
type collectionInfo struct {
@ -104,34 +112,48 @@ type MetaCache struct {
rootCoord types.RootCoord
queryCoord types.QueryCoord
collInfo map[string]*collectionInfo
credMap map[string]*internalpb.CredentialInfo // cache for credential, lazy load
mu sync.RWMutex
credMut sync.RWMutex
shardMgr *shardClientMgr
collInfo map[string]*collectionInfo
credMap map[string]*internalpb.CredentialInfo // cache for credential, lazy load
privilegeInfos map[string]struct{} // privileges cache
userToRoles map[string]map[string]struct{} // user to role cache
mu sync.RWMutex
credMut sync.RWMutex
privilegeMut sync.RWMutex
shardMgr *shardClientMgr
}
// globalMetaCache is singleton instance of Cache
var globalMetaCache Cache
// InitMetaCache initializes globalMetaCache
func InitMetaCache(rootCoord types.RootCoord, queryCoord types.QueryCoord, shardMgr *shardClientMgr) error {
func InitMetaCache(ctx context.Context, rootCoord types.RootCoord, queryCoord types.QueryCoord, shardMgr *shardClientMgr) error {
var err error
globalMetaCache, err = NewMetaCache(rootCoord, queryCoord, shardMgr)
if err != nil {
return err
}
// The privilege info is a little more. And to get this info, the query operation of involving multiple table queries is required.
resp, err := rootCoord.ListPolicy(ctx, &internalpb.ListPolicyRequest{})
if err != nil {
log.Error("fail to init meta cache", zap.Error(err))
return err
}
globalMetaCache.InitPolicyInfo(resp.PolicyInfos, resp.UserRoles)
log.Debug("success to init meta cache", zap.Strings("policy_infos", resp.PolicyInfos))
return nil
}
// NewMetaCache creates a MetaCache with provided RootCoord and QueryNode
func NewMetaCache(rootCoord types.RootCoord, queryCoord types.QueryCoord, shardMgr *shardClientMgr) (*MetaCache, error) {
return &MetaCache{
rootCoord: rootCoord,
queryCoord: queryCoord,
collInfo: map[string]*collectionInfo{},
credMap: map[string]*internalpb.CredentialInfo{},
shardMgr: shardMgr,
rootCoord: rootCoord,
queryCoord: queryCoord,
collInfo: map[string]*collectionInfo{},
credMap: map[string]*internalpb.CredentialInfo{},
shardMgr: shardMgr,
privilegeInfos: map[string]struct{}{},
userToRoles: map[string]map[string]struct{}{},
}, nil
}
@ -641,3 +663,60 @@ func (m *MetaCache) ClearShards(collectionName string) {
_ = m.shardMgr.UpdateShardLeaders(info.shardLeaders, nil)
}
}
func (m *MetaCache) InitPolicyInfo(info []string, userRoles []string) {
m.mu.Lock()
defer m.mu.Unlock()
m.privilegeInfos = util.StringSet(info)
for _, userRole := range userRoles {
user, role := funcutil.DecodeUserRoleCache(userRole)
if m.userToRoles[user] == nil {
m.userToRoles[user] = make(map[string]struct{})
}
m.userToRoles[user][role] = struct{}{}
}
}
func (m *MetaCache) GetPrivilegeInfo(ctx context.Context) []string {
m.mu.Lock()
defer m.mu.Unlock()
return util.StringList(m.privilegeInfos)
}
func (m *MetaCache) GetUserRole(user string) []string {
m.mu.Lock()
defer m.mu.Unlock()
return util.StringList(m.userToRoles[user])
}
func (m *MetaCache) RefreshPolicyInfo(op typeutil.CacheOp) error {
m.mu.Lock()
defer m.mu.Unlock()
if op.OpKey == "" {
return errors.New("empty op key")
}
switch op.OpType {
case typeutil.CacheGrantPrivilege:
m.privilegeInfos[op.OpKey] = struct{}{}
case typeutil.CacheRevokePrivilege:
delete(m.privilegeInfos, op.OpKey)
case typeutil.CacheAddUserToRole:
user, role := funcutil.DecodeUserRoleCache(op.OpKey)
if m.userToRoles[user] == nil {
m.userToRoles[user] = make(map[string]struct{})
}
m.userToRoles[user][role] = struct{}{}
case typeutil.CacheRemoveUserFromRole:
user, role := funcutil.DecodeUserRoleCache(op.OpKey)
if m.userToRoles[user] != nil {
delete(m.userToRoles[user], role)
}
default:
return fmt.Errorf("invalid opType, op_type: %d, op_key: %s", int(op.OpType), op.OpKey)
}
return nil
}

View File

@ -22,11 +22,14 @@ import (
"fmt"
"testing"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/proto/rootcoordpb"
@ -40,6 +43,8 @@ type MockRootCoordClientInterface struct {
types.RootCoord
Error bool
AccessCount int
listPolicy func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error)
}
type MockQueryCoordClientInterface struct {
@ -178,6 +183,17 @@ func (m *MockRootCoordClientInterface) ListCredUsers(ctx context.Context, req *m
}, nil
}
func (m *MockRootCoordClientInterface) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
if m.listPolicy != nil {
return m.listPolicy(ctx, in)
}
return &internalpb.ListPolicyResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
}, nil
}
func (m *MockQueryCoordClientInterface) ShowCollections(ctx context.Context, req *querypb.ShowCollectionsRequest) (*querypb.ShowCollectionsResponse, error) {
if m.Error {
return nil, errors.New("mocked error")
@ -199,7 +215,7 @@ func TestMetaCache_GetCollection(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
id, err := globalMetaCache.GetCollectionID(ctx, "collection1")
@ -247,7 +263,7 @@ func TestMetaCache_GetCollectionFailure(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
rootCoord.Error = true
@ -278,7 +294,7 @@ func TestMetaCache_GetNonExistCollection(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
id, err := globalMetaCache.GetCollectionID(ctx, "collection3")
@ -294,7 +310,7 @@ func TestMetaCache_GetPartitionID(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
id, err := globalMetaCache.GetPartitionID(ctx, "collection1", "par1")
@ -316,7 +332,7 @@ func TestMetaCache_GetPartitionError(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
// Test the case where ShowPartitionsResponse is not aligned
@ -344,16 +360,17 @@ func TestMetaCache_GetPartitionError(t *testing.T) {
}
func TestMetaCache_GetShards(t *testing.T) {
var (
ctx = context.Background()
collectionName = "collection1"
)
rootCoord := &MockRootCoordClientInterface{}
qc := NewQueryCoordMock()
shardMgr := newShardClientMgr()
err := InitMetaCache(rootCoord, qc, shardMgr)
err := InitMetaCache(ctx, rootCoord, qc, shardMgr)
require.Nil(t, err)
var (
ctx = context.TODO()
collectionName = "collection1"
)
qc.Init()
qc.Start()
defer qc.Stop()
@ -391,16 +408,17 @@ func TestMetaCache_GetShards(t *testing.T) {
}
func TestMetaCache_ClearShards(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
qc := NewQueryCoordMock()
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, qc, mgr)
require.Nil(t, err)
var (
ctx = context.TODO()
collectionName = "collection1"
)
rootCoord := &MockRootCoordClientInterface{}
qc := NewQueryCoordMock()
mgr := newShardClientMgr()
err := InitMetaCache(ctx, rootCoord, qc, mgr)
require.Nil(t, err)
qc.Init()
qc.Start()
defer qc.Stop()
@ -429,7 +447,88 @@ func TestMetaCache_ClearShards(t *testing.T) {
assert.Error(t, err)
assert.Empty(t, shards)
})
}
func TestMetaCache_PolicyInfo(t *testing.T) {
client := &MockRootCoordClientInterface{}
qc := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
t.Run("InitMetaCache", func(t *testing.T) {
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return nil, fmt.Errorf("mock error")
}
err := InitMetaCache(context.Background(), client, qc, mgr)
assert.NotNil(t, err)
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
PolicyInfos: []string{"policy1", "policy2", "policy3"},
}, nil
}
err = InitMetaCache(context.Background(), client, qc, mgr)
assert.Nil(t, err)
})
t.Run("GetPrivilegeInfo", func(t *testing.T) {
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
PolicyInfos: []string{"policy1", "policy2", "policy3"},
UserRoles: []string{funcutil.EncodeUserRoleCache("foo", "role1"), funcutil.EncodeUserRoleCache("foo", "role2"), funcutil.EncodeUserRoleCache("foo2", "role2")},
}, nil
}
err := InitMetaCache(context.Background(), client, qc, mgr)
assert.Nil(t, err)
policyInfos := globalMetaCache.GetPrivilegeInfo(context.Background())
assert.Equal(t, 3, len(policyInfos))
roles := globalMetaCache.GetUserRole("foo")
assert.Equal(t, 2, len(roles))
})
t.Run("GetPrivilegeInfo", func(t *testing.T) {
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
PolicyInfos: []string{"policy1", "policy2", "policy3"},
UserRoles: []string{funcutil.EncodeUserRoleCache("foo", "role1"), funcutil.EncodeUserRoleCache("foo", "role2"), funcutil.EncodeUserRoleCache("foo2", "role2")},
}, nil
}
err := InitMetaCache(context.Background(), client, qc, mgr)
assert.Nil(t, err)
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: typeutil.CacheGrantPrivilege, OpKey: "policyX"})
assert.Nil(t, err)
policyInfos := globalMetaCache.GetPrivilegeInfo(context.Background())
assert.Equal(t, 4, len(policyInfos))
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: typeutil.CacheRevokePrivilege, OpKey: "policyX"})
assert.Nil(t, err)
policyInfos = globalMetaCache.GetPrivilegeInfo(context.Background())
assert.Equal(t, 3, len(policyInfos))
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: typeutil.CacheAddUserToRole, OpKey: funcutil.EncodeUserRoleCache("foo", "role3")})
assert.Nil(t, err)
roles := globalMetaCache.GetUserRole("foo")
assert.Equal(t, 3, len(roles))
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: typeutil.CacheRemoveUserFromRole, OpKey: funcutil.EncodeUserRoleCache("foo", "role3")})
assert.Nil(t, err)
roles = globalMetaCache.GetUserRole("foo")
assert.Equal(t, 2, len(roles))
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: typeutil.CacheGrantPrivilege, OpKey: ""})
assert.NotNil(t, err)
err = globalMetaCache.RefreshPolicyInfo(typeutil.CacheOp{OpType: 100, OpKey: "policyX"})
assert.NotNil(t, err)
})
}
func TestMetaCache_LoadCache(t *testing.T) {
@ -437,7 +536,7 @@ func TestMetaCache_LoadCache(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, mgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, mgr)
assert.Nil(t, err)
t.Run("test IsCollectionLoaded", func(t *testing.T) {
@ -481,7 +580,7 @@ func TestMetaCache_RemoveCollection(t *testing.T) {
rootCoord := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
shardMgr := newShardClientMgr()
err := InitMetaCache(rootCoord, queryCoord, shardMgr)
err := InitMetaCache(ctx, rootCoord, queryCoord, shardMgr)
assert.Nil(t, err)
info, err := globalMetaCache.GetCollectionInfo(ctx, "collection1")

View File

@ -10,12 +10,14 @@ import (
type getCollectionIDFunc func(ctx context.Context, collectionName string) (typeutil.UniqueID, error)
type getCollectionSchemaFunc func(ctx context.Context, collectionName string) (*schemapb.CollectionSchema, error)
type getCollectionInfoFunc func(ctx context.Context, collectionName string) (*collectionInfo, error)
type getUserRoleFunc func(username string) []string
type mockCache struct {
Cache
getIDFunc getCollectionIDFunc
getSchemaFunc getCollectionSchemaFunc
getInfoFunc getCollectionInfoFunc
getIDFunc getCollectionIDFunc
getSchemaFunc getCollectionSchemaFunc
getInfoFunc getCollectionInfoFunc
getUserRoleFunc getUserRoleFunc
}
func (m *mockCache) GetCollectionID(ctx context.Context, collectionName string) (typeutil.UniqueID, error) {
@ -42,6 +44,13 @@ func (m *mockCache) GetCollectionInfo(ctx context.Context, collectionName string
func (m *mockCache) RemoveCollection(ctx context.Context, collectionName string) {
}
func (m *mockCache) GetUserRole(username string) []string {
if m.getUserRoleFunc != nil {
return m.getUserRoleFunc(username)
}
return []string{}
}
func (m *mockCache) setGetIDFunc(f getCollectionIDFunc) {
m.getIDFunc = f
}

View File

@ -0,0 +1,133 @@
package proxy
import (
"context"
"fmt"
"reflect"
"strings"
"github.com/milvus-io/milvus/internal/util"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
jsonadapter "github.com/casbin/json-adapter/v2"
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/util/funcutil"
"go.uber.org/zap"
"google.golang.org/grpc"
)
type PrivilegeFunc func(ctx context.Context, req interface{}) (context.Context, error)
const (
// sub -> role name, like admin, public
// obj -> contact object with object name, like Global-*, Collection-col1
// act -> privilege, like CreateCollection, DescribeCollection
ModelStr = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && globMatch(p.obj, r.obj) && globMatch(p.act, r.act) || r.sub == "admin" || r.act == "All"
`
ModelKey = "casbin"
)
var modelStore = make(map[string]model.Model, 1)
func initPolicyModel() (model.Model, error) {
if policyModel, ok := modelStore[ModelStr]; ok {
return policyModel, nil
}
policyModel, err := model.NewModelFromString(ModelStr)
if err != nil {
log.Error("NewModelFromString fail", zap.String("model", ModelStr), zap.Error(err))
return nil, err
}
modelStore[ModelKey] = policyModel
return modelStore[ModelKey], nil
}
// UnaryServerInterceptor returns a new unary server interceptors that performs per-request privilege access.
func UnaryServerInterceptor(privilegeFunc PrivilegeFunc) grpc.UnaryServerInterceptor {
initPolicyModel()
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
newCtx, err := privilegeFunc(ctx, req)
if err != nil {
return nil, err
}
return handler(newCtx, req)
}
}
func PrivilegeInterceptor(ctx context.Context, req interface{}) (context.Context, error) {
if !Params.CommonCfg.AuthorizationEnabled {
return ctx, nil
}
log.Debug("PrivilegeInterceptor", zap.String("type", reflect.TypeOf(req).String()))
privilegeExt, err := funcutil.GetPrivilegeExtObj(req)
if err != nil {
log.Debug("GetPrivilegeExtObj err", zap.Error(err))
return ctx, nil
}
username, err := GetCurUserFromContext(ctx)
if err != nil {
log.Error("GetCurUserFromContext fail", zap.Error(err))
return ctx, err
}
roleNames, err := GetRole(username)
if err != nil {
log.Error("GetRole fail", zap.String("username", username), zap.Error(err))
return ctx, err
}
roleNames = append(roleNames, util.RolePublic)
resourceType := privilegeExt.ObjectType.String()
resourceNameIndex := privilegeExt.ObjectNameIndex
resourceName := funcutil.GetResourceName(req, privilegeExt.ObjectNameIndex)
resourcePrivilege := privilegeExt.ObjectPrivilege.String()
policyInfo := strings.Join(globalMetaCache.GetPrivilegeInfo(ctx), ",")
log.Debug("current request info", zap.String("username", username), zap.Strings("role_names", roleNames),
zap.String("resource_type", resourceType), zap.String("resource_privilege", resourcePrivilege), zap.Int32("resource_index", resourceNameIndex), zap.String("resource_name", resourceName),
zap.String("policy_info", policyInfo))
policy := fmt.Sprintf("[%s]", strings.Join(globalMetaCache.GetPrivilegeInfo(ctx), ","))
b := []byte(policy)
a := jsonadapter.NewAdapter(&b)
policyModel, err := initPolicyModel()
if err != nil {
errStr := "fail to get policy model"
log.Error(errStr, zap.Error(err))
return ctx, err
}
e, err := casbin.NewEnforcer(policyModel, a)
if err != nil {
log.Error("NewEnforcer fail", zap.String("policy", policy), zap.Error(err))
return ctx, err
}
for _, roleName := range roleNames {
isPermit, err := e.Enforce(roleName, funcutil.PolicyForResource(resourceType, resourceName), privilegeExt.ObjectPrivilege.String())
if err != nil {
log.Error("Enforce fail", zap.String("policy", policy), zap.String("role", roleName), zap.Error(err))
return ctx, err
}
if isPermit {
return ctx, nil
}
}
log.Debug("permission deny", zap.String("policy", policy), zap.Strings("roles", roleNames))
return ctx, &ErrPermissionDenied{}
}
type ErrPermissionDenied struct{}
func (e ErrPermissionDenied) Error() string {
return "permission deny"
}

View File

@ -0,0 +1,94 @@
package proxy
import (
"context"
"testing"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/stretchr/testify/assert"
)
func TestUnaryServerInterceptor(t *testing.T) {
interceptor := UnaryServerInterceptor(PrivilegeInterceptor)
assert.NotNil(t, interceptor)
}
func TestPrivilegeInterceptor(t *testing.T) {
ctx := context.Background()
t.Run("Authorization Disabled", func(t *testing.T) {
Params.CommonCfg.AuthorizationEnabled = false
_, err := PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.Nil(t, err)
})
t.Run("Authorization Enabled", func(t *testing.T) {
Params.CommonCfg.AuthorizationEnabled = true
_, err := PrivilegeInterceptor(ctx, &milvuspb.HasCollectionRequest{})
assert.Nil(t, err)
_, err = PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.NotNil(t, err)
ctx = GetContext(context.Background(), "alice:123456")
client := &MockRootCoordClientInterface{}
queryCoord := &MockQueryCoordClientInterface{}
mgr := newShardClientMgr()
client.listPolicy = func(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
PolicyInfos: []string{
funcutil.PolicyForPrivilege("role1", commonpb.ObjectType_Collection.String(), "col1", commonpb.ObjectPrivilege_PrivilegeLoad.String()),
},
UserRoles: []string{
funcutil.EncodeUserRoleCache("alice", "role1"),
},
}, nil
}
_, err = PrivilegeInterceptor(GetContext(context.Background(), "foo:123456"), &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.NotNil(t, err)
err = InitMetaCache(ctx, client, queryCoord, mgr)
assert.Nil(t, err)
_, err = PrivilegeInterceptor(ctx, &milvuspb.HasCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.Nil(t, err)
_, err = PrivilegeInterceptor(ctx, &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.Nil(t, err)
_, err = PrivilegeInterceptor(GetContext(context.Background(), "foo:123456"), &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.NotNil(t, err)
_, err = PrivilegeInterceptor(ctx, &milvuspb.InsertRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.NotNil(t, err)
})
}

View File

@ -221,7 +221,7 @@ func (node *Proxy) Init() error {
log.Debug("create metrics cache manager done", zap.String("role", typeutil.ProxyRole))
log.Debug("init meta cache", zap.String("role", typeutil.ProxyRole))
if err := InitMetaCache(node.rootCoord, node.queryCoord, node.shardMgr); err != nil {
if err := InitMetaCache(node.ctx, node.rootCoord, node.queryCoord, node.shardMgr); err != nil {
log.Warn("failed to init meta cache", zap.Error(err), zap.String("role", typeutil.ProxyRole))
return err
}

View File

@ -19,6 +19,7 @@ package proxy
import (
"context"
"errors"
"fmt"
"net"
"os"
"strconv"
@ -38,6 +39,7 @@ import (
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/metrics"
"github.com/milvus-io/milvus/internal/rootcoord"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/crypto"
"github.com/milvus-io/milvus/internal/util/dependency"
@ -408,6 +410,7 @@ func TestProxy(t *testing.T) {
assert.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
ctx = GetContext(ctx, "root:123456")
localMsg := true
factory := dependency.NewDefaultFactory(localMsg)
alias := "TestProxy"
@ -2165,8 +2168,12 @@ func TestProxy(t *testing.T) {
Password: crypto.Base64Encode(password),
}
}
// success
createCredentialReq := constructCreateCredentialRequest()
// permission deny
invalidCtx := GetContext(context.Background(), "foo:12345")
_, err := proxy.CreateCredential(invalidCtx, createCredentialReq)
assert.Error(t, err)
// success
resp, err := proxy.CreateCredential(ctx, createCredentialReq)
assert.NoError(t, err)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
@ -2304,11 +2311,20 @@ func TestProxy(t *testing.T) {
}
}
delCredReq := constructDelCredRequest()
// permission deny
invalidCtx := GetContext(context.Background(), "foo:12345")
_, err := proxy.DeleteCredential(invalidCtx, delCredReq)
assert.Error(t, err)
deleteResp, err := proxy.DeleteCredential(ctx, delCredReq)
assert.NoError(t, err)
assert.Equal(t, commonpb.ErrorCode_Success, deleteResp.ErrorCode)
})
testProxyRole(ctx, t, proxy)
testProxyPrivilege(ctx, t, proxy)
testProxyRefreshPolicyInfoCache(ctx, t, proxy)
// proxy unhealthy
//
//notStateCode := "not state code"
@ -2593,6 +2609,58 @@ func TestProxy(t *testing.T) {
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
})
wg.Add(1)
t.Run("InvalidateCredCache fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.InvalidateCredentialCache(ctx, &proxypb.InvalidateCredCacheRequest{Username: "xxx"})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("UpdateCredentialCache fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.UpdateCredentialCache(ctx, &proxypb.UpdateCredCacheRequest{Username: "xxx", Password: "xxx"})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("CreateCredential fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.CreateCredential(ctx, &milvuspb.CreateCredentialRequest{Username: "xxx"})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("UpdateCredential fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.UpdateCredential(ctx, &milvuspb.UpdateCredentialRequest{Username: "xxx"})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("DeleteCredential fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.DeleteCredential(ctx, &milvuspb.DeleteCredentialRequest{Username: "xxx"})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("ListCredUsers fail, unhealthy", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.ListCredUsers(ctx, &milvuspb.ListCredUsersRequest{})
assert.Error(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
})
testProxyRoleUnhealthy(ctx, t, proxy)
testProxyPrivilegeUnhealthy(ctx, t, proxy)
testProxyRefreshPolicyInfoCacheUnhealthy(ctx, t, proxy)
proxy.UpdateStateCode(internalpb.StateCode_Healthy)
// queue full
@ -3100,12 +3168,464 @@ func TestProxy(t *testing.T) {
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
testProxyRoleTimeout(shortCtx, t, proxy)
testProxyPrivilegeTimeout(shortCtx, t, proxy)
testServer.gracefulStop()
wg.Wait()
cancel()
}
func getNotRootCtx() context.Context {
return GetContext(context.Background(), "foo:12345")
}
func testProxyRole(ctx context.Context, t *testing.T, proxy *Proxy) {
var wg sync.WaitGroup
wg.Add(1)
t.Run("Create Role", func(t *testing.T) {
defer wg.Done()
entity := &milvuspb.RoleEntity{Name: " "}
resp, _ := proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: entity})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
entity.Name = "unit_test"
_, err := proxy.CreateRole(getNotRootCtx(), &milvuspb.CreateRoleRequest{Entity: entity})
assert.Error(t, err)
resp, _ = proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: entity})
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: entity})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: entity.Name})
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("Drop Role", func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: " "})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
username := "root"
roleName := "unit_test"
roleEntity := &milvuspb.RoleEntity{Name: roleName}
roleResp, _ := proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: roleEntity})
assert.Equal(t, commonpb.ErrorCode_Success, roleResp.ErrorCode)
privilegeRequest := &milvuspb.OperatePrivilegeRequest{
Type: milvuspb.OperatePrivilegeType_Grant,
Entity: &milvuspb.GrantEntity{
ObjectName: "col1",
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
Role: &milvuspb.RoleEntity{Name: roleName},
Grantor: &milvuspb.GrantorEntity{Privilege: &milvuspb.PrivilegeEntity{Name: util.Load.String()}},
},
}
privilegeResp, _ := proxy.OperatePrivilege(ctx, privilegeRequest)
assert.Equal(t, commonpb.ErrorCode_Success, privilegeResp.ErrorCode)
_, err := proxy.SelectUser(context.Background(), &milvuspb.SelectUserRequest{User: &milvuspb.UserEntity{Name: username}, IncludeRoleInfo: true})
assert.Error(t, err)
_, err = proxy.SelectUser(getNotRootCtx(), &milvuspb.SelectUserRequest{User: &milvuspb.UserEntity{Name: username}, IncludeRoleInfo: true})
assert.Error(t, err)
userResp, _ := proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: &milvuspb.UserEntity{Name: username}, IncludeRoleInfo: true})
assert.Equal(t, commonpb.ErrorCode_Success, userResp.Status.ErrorCode)
roleNumOfUser := len(userResp.Results[0].Roles)
_, err = proxy.OperateUserRole(getNotRootCtx(), &milvuspb.OperateUserRoleRequest{
Username: username,
RoleName: roleName,
Type: milvuspb.OperateUserRoleType_AddUserToRole,
})
assert.Error(t, err)
roleResp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{
Username: username,
RoleName: roleName,
Type: milvuspb.OperateUserRoleType_AddUserToRole,
})
assert.Equal(t, commonpb.ErrorCode_Success, roleResp.ErrorCode)
resp, _ = proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: roleName})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
privilegeRequest.Type = milvuspb.OperatePrivilegeType_Revoke
privilegeResp, _ = proxy.OperatePrivilege(ctx, privilegeRequest)
assert.Equal(t, commonpb.ErrorCode_Success, privilegeResp.ErrorCode)
_, err = proxy.DropRole(getNotRootCtx(), &milvuspb.DropRoleRequest{RoleName: roleName})
assert.Error(t, err)
roleResp, _ = proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: roleName})
assert.Equal(t, commonpb.ErrorCode_Success, roleResp.ErrorCode)
userResp, _ = proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: &milvuspb.UserEntity{Name: username}, IncludeRoleInfo: true})
assert.Equal(t, commonpb.ErrorCode_Success, userResp.Status.ErrorCode)
assert.Equal(t, roleNumOfUser, len(userResp.Results[0].Roles))
})
wg.Add(1)
t.Run("Operate User Role", func(t *testing.T) {
defer wg.Done()
username := "root"
roleName := "public"
// AddUserToRole
resp, _ := proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: " "})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: username, RoleName: " "})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: "not_existed", RoleName: roleName})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: username, RoleName: "not_existed"})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: username, RoleName: roleName})
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
resp, _ = proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: username, RoleName: roleName, Type: milvuspb.OperateUserRoleType_RemoveUserFromRole})
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run("Select Role", func(t *testing.T) {
defer wg.Done()
_, err := proxy.SelectRole(ctx, &milvuspb.SelectRoleRequest{Role: &milvuspb.RoleEntity{Name: " "}})
assert.Error(t, err)
_, err = proxy.SelectRole(getNotRootCtx(), &milvuspb.SelectRoleRequest{Role: &milvuspb.RoleEntity{Name: " "}})
assert.Error(t, err)
resp, _ := proxy.SelectRole(ctx, &milvuspb.SelectRoleRequest{})
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
roleNum := len(resp.Results)
roleName := "unit_test"
roleResp, _ := proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: &milvuspb.RoleEntity{Name: roleName}})
assert.Equal(t, commonpb.ErrorCode_Success, roleResp.ErrorCode)
resp, _ = proxy.SelectRole(ctx, &milvuspb.SelectRoleRequest{})
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
assert.Equal(t, roleNum+1, len(resp.Results))
roleResp, _ = proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: roleName})
assert.Equal(t, commonpb.ErrorCode_Success, roleResp.ErrorCode)
resp, _ = proxy.SelectRole(ctx, &milvuspb.SelectRoleRequest{Role: &milvuspb.RoleEntity{Name: "admin"}, IncludeUserInfo: true})
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
assert.NotEqual(t, 0, len(resp.Results))
assert.NotEqual(t, 0, len(resp.Results[0].Users))
})
wg.Add(1)
t.Run("Select User", func(t *testing.T) {
defer wg.Done()
entity := &milvuspb.UserEntity{Name: " "}
resp, _ := proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: entity})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
entity.Name = "not_existed"
resp, _ = proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: entity})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
entity.Name = "root"
resp, _ = proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: entity})
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
assert.NotEqual(t, 0, len(resp.Results))
resp, _ = proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{User: entity, IncludeRoleInfo: true})
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
assert.NotEqual(t, 0, len(resp.Results))
assert.NotEqual(t, 0, len(resp.Results[0].Roles))
})
wg.Wait()
}
func testProxyRoleUnhealthy(ctx context.Context, t *testing.T, proxy *Proxy) {
testProxyRoleFail(ctx, t, proxy, "unhealthy")
}
func testProxyRoleTimeout(ctx context.Context, t *testing.T, proxy *Proxy) {
testProxyRoleFail(ctx, t, proxy, "timeout")
}
func testProxyRoleFail(ctx context.Context, t *testing.T, proxy *Proxy, reason string) {
var wg sync.WaitGroup
roleName := "xxx"
wg.Add(1)
t.Run(fmt.Sprintf("CreateRole fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.CreateRole(ctx, &milvuspb.CreateRoleRequest{Entity: &milvuspb.RoleEntity{Name: roleName}})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run(fmt.Sprintf("DropRole fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.DropRole(ctx, &milvuspb.DropRoleRequest{RoleName: roleName})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run(fmt.Sprintf("OperateUserRole fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{Username: "root", RoleName: "public"})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run(fmt.Sprintf("SelectRole fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.SelectRole(ctx, &milvuspb.SelectRoleRequest{})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
})
wg.Add(1)
t.Run(fmt.Sprintf("SelectUser fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.SelectUser(ctx, &milvuspb.SelectUserRequest{})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
})
wg.Wait()
}
func testProxyPrivilege(ctx context.Context, t *testing.T, proxy *Proxy) {
var wg sync.WaitGroup
wg.Add(1)
t.Run("Operate Privilege, Select Grant", func(t *testing.T) {
defer wg.Done()
// GrantPrivilege
req := &milvuspb.OperatePrivilegeRequest{}
resp, _ := proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity = &milvuspb.GrantEntity{}
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Grantor = &milvuspb.GrantorEntity{}
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Grantor.Privilege = &milvuspb.PrivilegeEntity{}
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Grantor.Privilege.Name = util.All.String()
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Object = &milvuspb.ObjectEntity{}
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Object.Name = commonpb.ObjectType_Global.String()
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.ObjectName = "col1"
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Role = &milvuspb.RoleEntity{}
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Role = &milvuspb.RoleEntity{Name: "admin"}
_, err := proxy.OperatePrivilege(getNotRootCtx(), req)
assert.Error(t, err)
_, err = proxy.OperatePrivilege(context.Background(), req)
assert.Error(t, err)
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Grantor.Privilege.Name = "not existed"
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Grantor.Privilege.Name = util.All.String()
req.Entity.Object.Name = "not existed"
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Object.Name = commonpb.ObjectType_Global.String()
req.Entity.Role.Name = "not existed"
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
req.Entity.Role = &milvuspb.RoleEntity{Name: "admin"}
roleReq := &milvuspb.OperatePrivilegeRequest{
Entity: &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: "public"},
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
ObjectName: "col1",
Grantor: &milvuspb.GrantorEntity{Privilege: &milvuspb.PrivilegeEntity{Name: util.Load.String()}},
},
Type: milvuspb.OperatePrivilegeType_Grant,
}
resp, _ = proxy.OperatePrivilege(ctx, roleReq)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
// select grant
selectReq := &milvuspb.SelectGrantRequest{}
results, _ := proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity = &milvuspb.GrantEntity{}
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.Object = &milvuspb.ObjectEntity{}
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.Object.Name = commonpb.ObjectType_Collection.String()
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.ObjectName = "col1"
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.Role = &milvuspb.RoleEntity{}
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.Role = &milvuspb.RoleEntity{Name: "public"}
_, err = proxy.SelectGrant(getNotRootCtx(), selectReq)
assert.Error(t, err)
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.Equal(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
assert.NotEqual(t, 0, len(results.Entities))
selectReq.Entity.Object.Name = "not existed"
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
selectReq.Entity.Object.Name = commonpb.ObjectType_Collection.String()
selectReq.Entity.Role = &milvuspb.RoleEntity{Name: "not existed"}
results, _ = proxy.SelectGrant(ctx, selectReq)
assert.NotEqual(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
results, _ = proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
Entity: &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: "public"},
},
})
assert.Equal(t, commonpb.ErrorCode_Success, results.Status.ErrorCode)
assert.NotEqual(t, 0, len(results.Entities))
req.Type = milvuspb.OperatePrivilegeType_Revoke
resp, _ = proxy.OperatePrivilege(ctx, req)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
roleReq.Type = milvuspb.OperatePrivilegeType_Revoke
resp, _ = proxy.OperatePrivilege(ctx, roleReq)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Wait()
}
func testProxyPrivilegeUnhealthy(ctx context.Context, t *testing.T, proxy *Proxy) {
testProxyPrivilegeFail(ctx, t, proxy, "unhealthy")
}
func testProxyPrivilegeTimeout(ctx context.Context, t *testing.T, proxy *Proxy) {
testProxyPrivilegeFail(ctx, t, proxy, "timeout")
}
func testProxyPrivilegeFail(ctx context.Context, t *testing.T, proxy *Proxy, reason string) {
var wg sync.WaitGroup
wg.Add(1)
t.Run(fmt.Sprintf("Operate Grant fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{
Entity: &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: "admin"},
ObjectName: "col1",
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()},
Grantor: &milvuspb.GrantorEntity{Privilege: &milvuspb.PrivilegeEntity{Name: util.All.String()}},
},
})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Add(1)
t.Run(fmt.Sprintf("SelectGrant fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.SelectGrant(ctx, &milvuspb.SelectGrantRequest{
Entity: &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: "admin"},
},
})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
})
wg.Wait()
}
func testProxyRefreshPolicyInfoCache(ctx context.Context, t *testing.T, proxy *Proxy) {
var wg sync.WaitGroup
wg.Add(1)
t.Run("RefreshPolicyInfoCache", func(t *testing.T) {
defer wg.Done()
resp, err := proxy.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
OpType: int32(typeutil.CacheAddUserToRole),
OpKey: funcutil.EncodeUserRoleCache("foo", "public"),
})
assert.NoError(t, err)
assert.Equal(t, commonpb.ErrorCode_Success, resp.ErrorCode)
_, err = proxy.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{})
assert.Error(t, err)
_, err = proxy.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
OpType: 100,
OpKey: funcutil.EncodeUserRoleCache("foo", "public"),
})
assert.Error(t, err)
})
wg.Wait()
}
func testProxyRefreshPolicyInfoCacheUnhealthy(ctx context.Context, t *testing.T, proxy *Proxy) {
testProxyRefreshPolicyInfoCacheFail(ctx, t, proxy, "unhealthy")
}
func testProxyRefreshPolicyInfoCacheFail(ctx context.Context, t *testing.T, proxy *Proxy, reason string) {
var wg sync.WaitGroup
wg.Add(1)
t.Run(fmt.Sprintf("RefreshPolicyInfoCache fail, %s", reason), func(t *testing.T) {
defer wg.Done()
resp, _ := proxy.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
OpType: int32(typeutil.CacheAddUserToRole),
OpKey: funcutil.EncodeUserRoleCache("foo", "public"),
})
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
})
wg.Wait()
}
func Test_GetCompactionState(t *testing.T) {
t.Run("get compaction state", func(t *testing.T) {
datacoord := &DataCoordMock{}

View File

@ -1081,6 +1081,38 @@ func (coord *RootCoordMock) GetCredential(ctx context.Context, req *rootcoordpb.
return &rootcoordpb.GetCredentialResponse{}, nil
}
func (coord *RootCoordMock) CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
return &commonpb.Status{}, nil
}
func (coord *RootCoordMock) DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
return &commonpb.Status{}, nil
}
func (coord *RootCoordMock) OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
return &commonpb.Status{}, nil
}
func (coord *RootCoordMock) SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
return &milvuspb.SelectRoleResponse{}, nil
}
func (coord *RootCoordMock) SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
return &milvuspb.SelectUserResponse{}, nil
}
func (coord *RootCoordMock) OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
return &commonpb.Status{}, nil
}
func (coord *RootCoordMock) SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
return &milvuspb.SelectGrantResponse{}, nil
}
func (coord *RootCoordMock) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{}, nil
}
type DescribeCollectionFunc func(ctx context.Context, request *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error)
type ShowPartitionsFunc func(ctx context.Context, request *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error)
type DescribeIndexFunc func(ctx context.Context, request *milvuspb.DescribeIndexRequest) (*milvuspb.DescribeIndexResponse, error)
@ -1158,6 +1190,10 @@ func (m *mockRootCoord) GetIndexState(ctx context.Context, request *milvuspb.Get
return nil, errors.New("mock")
}
func (m *mockRootCoord) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
return &internalpb.ListPolicyResponse{}, nil
}
func newMockRootCoord() *mockRootCoord {
return &mockRootCoord{}
}

View File

@ -60,7 +60,7 @@ func TestGetIndexStateTask_Execute(t *testing.T) {
shardMgr := newShardClientMgr()
// failed to get collection id.
_ = InitMetaCache(rootCoord, queryCoord, shardMgr)
_ = InitMetaCache(ctx, rootCoord, queryCoord, shardMgr)
assert.Error(t, gist.Execute(ctx))
rootCoord.GetIndexStateFunc = func(ctx context.Context, request *milvuspb.GetIndexStateRequest) (*indexpb.GetIndexStatesResponse, error) {
return &indexpb.GetIndexStatesResponse{

View File

@ -56,7 +56,7 @@ func TestQueryTask_all(t *testing.T) {
qc.Start()
defer qc.Stop()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
assert.NoError(t, err)
fieldName2Types := map[string]schemapb.DataType{

View File

@ -123,7 +123,7 @@ func TestSearchTask_PreExecute(t *testing.T) {
defer rc.Stop()
require.NoError(t, err)
mgr := newShardClientMgr()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
require.NoError(t, err)
err = qc.Start()
@ -335,7 +335,7 @@ func TestSearchTaskV2_Execute(t *testing.T) {
require.NoError(t, err)
defer rc.Stop()
mgr := newShardClientMgr()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
require.NoError(t, err)
err = qc.Start()
@ -442,7 +442,7 @@ func TestSearchTaskWithInvalidRoundDecimal(t *testing.T) {
//
// ctx := context.Background()
//
// err = InitMetaCache(rc)
// err = InitMetaCache(ctx, rc)
// assert.NoError(t, err)
//
// shardsNum := int32(2)
@ -685,7 +685,7 @@ func TestSearchTaskV2_all(t *testing.T) {
//
// ctx := context.Background()
//
// err = InitMetaCache(rc)
// err = InitMetaCache(ctx, rc)
// assert.NoError(t, err)
//
// shardsNum := int32(2)
@ -930,7 +930,7 @@ func TestSearchTaskV2_7803_reduce(t *testing.T) {
//
// ctx := context.Background()
//
// err = InitMetaCache(rc)
// err = InitMetaCache(ctx, rc)
// assert.NoError(t, err)
//
// shardsNum := int32(2)
@ -1619,7 +1619,7 @@ func TestSearchTask_ErrExecute(t *testing.T) {
qc.Start()
defer qc.Stop()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
assert.NoError(t, err)
fieldName2Types := map[string]schemapb.DataType{

View File

@ -830,7 +830,7 @@ func TestHasCollectionTask(t *testing.T) {
defer qc.Stop()
ctx := context.Background()
mgr := newShardClientMgr()
InitMetaCache(rc, qc, mgr)
InitMetaCache(ctx, rc, qc, mgr)
prefix := "TestHasCollectionTask"
dbName := ""
collectionName := prefix + funcutil.GenRandomStr()
@ -916,7 +916,7 @@ func TestDescribeCollectionTask(t *testing.T) {
defer qc.Stop()
ctx := context.Background()
mgr := newShardClientMgr()
InitMetaCache(rc, qc, mgr)
InitMetaCache(ctx, rc, qc, mgr)
prefix := "TestDescribeCollectionTask"
dbName := ""
collectionName := prefix + funcutil.GenRandomStr()
@ -979,7 +979,7 @@ func TestDescribeCollectionTask_ShardsNum1(t *testing.T) {
defer qc.Stop()
ctx := context.Background()
mgr := newShardClientMgr()
InitMetaCache(rc, qc, mgr)
InitMetaCache(ctx, rc, qc, mgr)
prefix := "TestDescribeCollectionTask"
dbName := ""
collectionName := prefix + funcutil.GenRandomStr()
@ -1044,7 +1044,7 @@ func TestDescribeCollectionTask_ShardsNum2(t *testing.T) {
defer qc.Stop()
ctx := context.Background()
mgr := newShardClientMgr()
InitMetaCache(rc, qc, mgr)
InitMetaCache(ctx, rc, qc, mgr)
prefix := "TestDescribeCollectionTask"
dbName := ""
collectionName := prefix + funcutil.GenRandomStr()
@ -1311,7 +1311,7 @@ func TestTask_Int64PrimaryKey(t *testing.T) {
ctx := context.Background()
mgr := newShardClientMgr()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
assert.NoError(t, err)
shardsNum := int32(2)
@ -1565,7 +1565,7 @@ func TestTask_VarCharPrimaryKey(t *testing.T) {
ctx := context.Background()
mgr := newShardClientMgr()
err = InitMetaCache(rc, qc, mgr)
err = InitMetaCache(ctx, rc, qc, mgr)
assert.NoError(t, err)
shardsNum := int32(2)

View File

@ -17,12 +17,20 @@
package proxy
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/milvus-io/milvus/internal/log"
"go.uber.org/zap"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/crypto"
"google.golang.org/grpc/metadata"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/schemapb"
"github.com/milvus-io/milvus/internal/util/tsoutil"
@ -39,6 +47,8 @@ const enableMultipleVectorFields = false
const maxVarCharLengthKey = "max_length"
const defaultMaxVarCharLength = 65535
var logger = log.L().WithOptions(zap.Fields(zap.String("role", typeutil.ProxyRole)))
// isAlpha check if c is alpha.
func isAlpha(c uint8) bool {
if (c < 'A' || c > 'Z') && (c < 'a' || c > 'z') {
@ -593,3 +603,114 @@ func parseGuaranteeTs(ts, tMax typeutil.Timestamp) typeutil.Timestamp {
}
return ts
}
func validateName(entity string, nameType string) error {
entity = strings.TrimSpace(entity)
if entity == "" {
return fmt.Errorf("%s should not be empty", nameType)
}
invalidMsg := fmt.Sprintf("invalid %s: %s. ", nameType, entity)
if int64(len(entity)) > Params.ProxyCfg.MaxNameLength {
msg := invalidMsg + fmt.Sprintf("the length of %s must be less than ", nameType) +
strconv.FormatInt(Params.ProxyCfg.MaxNameLength, 10) + " characters."
return errors.New(msg)
}
firstChar := entity[0]
if firstChar != '_' && !isAlpha(firstChar) {
msg := invalidMsg + fmt.Sprintf("the first character of %s must be an underscore or letter.", nameType)
return errors.New(msg)
}
for i := 1; i < len(entity); i++ {
c := entity[i]
if c != '_' && c != '$' && !isAlpha(c) && !isNumber(c) {
msg := invalidMsg + fmt.Sprintf("%s can only contain numbers, letters, dollars and underscores.", nameType)
return errors.New(msg)
}
}
return nil
}
func ValidateRoleName(entity string) error {
return validateName(entity, "role name")
}
func ValidateObjectName(entity string) error {
entity = strings.TrimSpace(entity)
if entity == "" {
return fmt.Errorf("objectName should not be empty")
}
if int64(len(entity)) > Params.ProxyCfg.MaxNameLength {
msg := fmt.Sprintf("invalid object name: %s. The length of resource name must be less than %s characters",
entity, strconv.FormatInt(Params.ProxyCfg.MaxNameLength, 10))
return errors.New(msg)
}
return nil
}
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 {
return validateName(entity, "Privilege")
}
func GetCurUserFromContext(ctx context.Context) (string, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return "", fmt.Errorf("fail to get md from the context")
}
authorization := md[strings.ToLower(util.HeaderAuthorize)]
if len(authorization) < 1 {
return "", fmt.Errorf("fail to get authorization from the md, authorize:[%s]", util.HeaderAuthorize)
}
token := authorization[0]
rawToken, err := crypto.Base64Decode(token)
if err != nil {
return "", fmt.Errorf("fail to decode the token, token: %s", token)
}
secrets := strings.SplitN(rawToken, util.CredentialSeperator, 2)
if len(secrets) < 2 {
return "", fmt.Errorf("fail to get user info from the raw token, raw token: %s", rawToken)
}
username := secrets[0]
return username, nil
}
func GetRole(username string) ([]string, error) {
if globalMetaCache == nil {
return []string{}, ErrProxyNotReady()
}
return globalMetaCache.GetUserRole(username), nil
}
func ValidateAdminPermission(ctx context.Context) error {
curUser, err := GetCurUserFromContext(ctx)
if err != nil {
return fmt.Errorf("fail to get current user info from the context, err: %w", err)
}
roles, err := GetRole(curUser)
if err != nil {
return fmt.Errorf("fail to get role for the current user info, currtent user:%s, err: %w", curUser, err)
}
for _, role := range roles {
if role == util.RoleAdmin {
return nil
}
}
return fmt.Errorf("the current user doesn't have privileges of the admin role, can't execute this api")
}

View File

@ -17,12 +17,18 @@
package proxy
import (
"context"
"fmt"
"strconv"
"strings"
"testing"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/schemapb"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/crypto"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
)
func TestValidateCollectionName(t *testing.T) {
@ -616,3 +622,121 @@ func TestReplaceID2Name(t *testing.T) {
dstStr := "collection default_collection has not been loaded to memory or load failed"
assert.Equal(t, dstStr, ReplaceID2Name(srcStr, int64(432682805904801793), "default_collection"))
}
func TestValidateName(t *testing.T) {
Params.InitOnce()
nameType := "Test"
validNames := []string{
"abc",
"_123abc",
}
for _, name := range validNames {
assert.Nil(t, validateName(name, nameType))
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))
}
longName := make([]byte, 256)
for i := 0; i < len(longName); i++ {
longName[i] = 'a'
}
invalidNames := []string{
" ",
"123abc",
"$abc",
"_12 ac",
" ",
"",
string(longName),
"中文",
}
for _, name := range invalidNames {
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(" "))
assert.NotNil(t, ValidateObjectName(string(longName)))
}
func GetContext(ctx context.Context, originValue string) context.Context {
authKey := strings.ToLower(util.HeaderAuthorize)
authValue := crypto.Base64Encode(originValue)
contextMap := map[string]string{
authKey: authValue,
}
md := metadata.New(contextMap)
return metadata.NewIncomingContext(ctx, md)
}
func TestGetCurUserFromContext(t *testing.T) {
_, err := GetCurUserFromContext(context.Background())
assert.NotNil(t, err)
_, err = GetCurUserFromContext(metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{})))
assert.NotNil(t, err)
_, err = GetCurUserFromContext(GetContext(context.Background(), "123456"))
assert.NotNil(t, err)
root := "root"
password := "123456"
username, err := GetCurUserFromContext(GetContext(context.Background(), fmt.Sprintf("%s%s%s", root, util.CredentialSeperator, password)))
assert.Nil(t, err)
assert.Equal(t, "root", username)
}
func TestGetRole(t *testing.T) {
globalMetaCache = nil
_, err := GetRole("foo")
assert.NotNil(t, err)
globalMetaCache = &mockCache{
getUserRoleFunc: func(username string) []string {
if username == "root" {
return []string{"role1", "admin", "role2"}
}
return []string{"role1"}
},
}
roles, err := GetRole("root")
assert.Nil(t, err)
assert.Equal(t, 3, len(roles))
roles, err = GetRole("foo")
assert.Nil(t, err)
assert.Equal(t, 1, len(roles))
}
func TestValidateAdminPermission(t *testing.T) {
root := "root"
password := "123456"
err := ValidateAdminPermission(context.Background())
assert.NotNil(t, err)
globalMetaCache = nil
err = ValidateAdminPermission(GetContext(context.Background(), fmt.Sprintf("%s%s%s", root, util.CredentialSeperator, password)))
assert.NotNil(t, err)
globalMetaCache = &mockCache{
getUserRoleFunc: func(username string) []string {
if username == "root" {
return []string{"role1", "admin", "role2"}
}
return []string{"role1"}
},
}
err = ValidateAdminPermission(GetContext(context.Background(), fmt.Sprintf("%s%s%s", root, util.CredentialSeperator, password)))
assert.Nil(t, err)
err = ValidateAdminPermission(GetContext(context.Background(), fmt.Sprintf("%s%s%s", "test", util.CredentialSeperator, password)))
assert.NotNil(t, err)
}

View File

@ -21,6 +21,8 @@ import (
"fmt"
"sync"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/kv"
@ -1350,3 +1352,88 @@ func (mt *MetaTable) getSegIdxMetaBySegID(segID int64) (model.SegmentIndex, erro
return segmentIdx, nil
}
// CreateRole create role
func (mt *MetaTable) CreateRole(tenant string, entity *milvuspb.RoleEntity) error {
if funcutil.IsEmptyString(entity.Name) {
return fmt.Errorf("the role name in the role info is empty")
}
return mt.catalog.CreateRole(mt.ctx, tenant, entity)
}
// DropRole drop role info
func (mt *MetaTable) DropRole(tenant string, roleName string) error {
return mt.catalog.DropRole(mt.ctx, tenant, roleName)
}
// OperateUserRole operate the relationship between a user and a role, including adding a user to a role and removing a user from a role
func (mt *MetaTable) OperateUserRole(tenant string, userEntity *milvuspb.UserEntity, roleEntity *milvuspb.RoleEntity, operateType milvuspb.OperateUserRoleType) error {
if funcutil.IsEmptyString(userEntity.Name) {
return fmt.Errorf("username in the user entity is empty")
}
if funcutil.IsEmptyString(roleEntity.Name) {
return fmt.Errorf("role name in the role entity is empty")
}
return mt.catalog.OperateUserRole(mt.ctx, tenant, userEntity, roleEntity, operateType)
}
// SelectRole select role.
// Enter the role condition by the entity param. And this param is nil, which means selecting all roles.
// Get all users that are added to the role by setting the includeUserInfo param to true.
func (mt *MetaTable) SelectRole(tenant string, entity *milvuspb.RoleEntity, includeUserInfo bool) ([]*milvuspb.RoleResult, error) {
return mt.catalog.SelectRole(mt.ctx, tenant, entity, includeUserInfo)
}
// SelectUser select user.
// Enter the user condition by the entity param. And this param is nil, which means selecting all users.
// Get all roles that are added the user to by setting the includeRoleInfo param to true.
func (mt *MetaTable) SelectUser(tenant string, entity *milvuspb.UserEntity, includeRoleInfo bool) ([]*milvuspb.UserResult, error) {
return mt.catalog.SelectUser(mt.ctx, tenant, entity, includeRoleInfo)
}
// OperatePrivilege grant or revoke privilege by setting the operateType param
func (mt *MetaTable) OperatePrivilege(tenant string, entity *milvuspb.GrantEntity, operateType milvuspb.OperatePrivilegeType) error {
if funcutil.IsEmptyString(entity.ObjectName) {
return fmt.Errorf("the object name in the grant entity is empty")
}
if entity.Object == nil || funcutil.IsEmptyString(entity.Object.Name) {
return fmt.Errorf("the object entity in the grant entity is invalid")
}
if entity.Role == nil || funcutil.IsEmptyString(entity.Role.Name) {
return fmt.Errorf("the role entity in the grant entity is invalid")
}
if entity.Grantor == nil {
return fmt.Errorf("the grantor in the grant entity is empty")
}
if entity.Grantor.Privilege == nil || funcutil.IsEmptyString(entity.Grantor.Privilege.Name) {
return fmt.Errorf("the privilege name in the grant entity is empty")
}
if entity.Grantor.User == nil || funcutil.IsEmptyString(entity.Grantor.User.Name) {
return fmt.Errorf("the grantor name in the grant entity is empty")
}
if !funcutil.IsRevoke(operateType) && !funcutil.IsGrant(operateType) {
return fmt.Errorf("the operate type in the grant entity is invalid")
}
return mt.catalog.OperatePrivilege(mt.ctx, tenant, entity, operateType)
}
// SelectGrant select grant
// The principal entity MUST be not empty in the grant entity
// The resource entity and the resource name are optional, and the two params should be not empty together when you select some grants about the resource kind.
func (mt *MetaTable) SelectGrant(tenant string, entity *milvuspb.GrantEntity) ([]*milvuspb.GrantEntity, error) {
var entities []*milvuspb.GrantEntity
if entity.Role == nil || funcutil.IsEmptyString(entity.Role.Name) {
return entities, fmt.Errorf("the role entity in the grant entity is invalid")
}
return mt.catalog.SelectGrant(mt.ctx, tenant, entity)
}
func (mt *MetaTable) ListPolicy(tenant string) ([]string, error) {
return mt.catalog.ListPolicy(mt.ctx, tenant)
}
func (mt *MetaTable) ListUserRole(tenant string) ([]string, error) {
return mt.catalog.ListUserRole(mt.ctx, tenant)
}

View File

@ -18,14 +18,22 @@ package rootcoord
import (
"context"
"encoding/json"
"errors"
"fmt"
"math/rand"
"path"
"strings"
"sync"
"testing"
"time"
"go.uber.org/zap"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/metastore"
@ -47,7 +55,7 @@ import (
)
type mockTestKV struct {
kv.TxnKV
kv.SnapShotKV
loadWithPrefix func(key string, ts typeutil.Timestamp) ([]string, []string, error)
save func(key, value string, ts typeutil.Timestamp) error
@ -82,6 +90,7 @@ type mockTestTxnKV struct {
multiSaveAndRemoveWithPrefix func(saves map[string]string, removals []string) error
remove func(key string) error
multiRemove func(keys []string) error
load func(key string) (string, error)
}
func (m *mockTestTxnKV) LoadWithPrefix(key string) ([]string, []string, error) {
@ -108,6 +117,49 @@ func (m *mockTestTxnKV) MultiRemove(keys []string) error {
return m.multiRemove(keys)
}
func (m *mockTestTxnKV) Load(key string) (string, error) {
return m.load(key)
}
func generateMetaTable(t *testing.T) (*MetaTable, *mockTestKV, *mockTestTxnKV, func()) {
rand.Seed(time.Now().UnixNano())
randVal := rand.Int()
Params.Init()
rootPath := fmt.Sprintf("/test/meta/%d", randVal)
etcdCli, err := etcd.GetEtcdClient(&Params.EtcdCfg)
require.Nil(t, err)
skv, err := kvmetestore.NewMetaSnapshot(etcdCli, rootPath, TimestampPrefix, 7)
assert.Nil(t, err)
assert.NotNil(t, skv)
txnkv := etcdkv.NewEtcdKV(etcdCli, rootPath)
mt, err := NewMetaTable(context.TODO(), txnkv, skv)
assert.Nil(t, err)
mockSnapshotKV := &mockTestKV{
SnapShotKV: mt.snapshot,
loadWithPrefix: func(key string, ts typeutil.Timestamp) ([]string, []string, error) {
return skv.LoadWithPrefix(key, ts)
},
}
mockTxnKV := &mockTestTxnKV{
TxnKV: mt.txn,
loadWithPrefix: func(key string) ([]string, []string, error) { return txnkv.LoadWithPrefix(key) },
save: func(key, value string) error { return txnkv.Save(key, value) },
multiSave: func(kvs map[string]string) error { return txnkv.MultiSave(kvs) },
multiSaveAndRemoveWithPrefix: func(kvs map[string]string, removal []string) error {
return txnkv.MultiSaveAndRemoveWithPrefix(kvs, removal)
},
remove: func(key string) error { return txnkv.Remove(key) },
}
mockMt, err := NewMetaTable(context.TODO(), mockTxnKV, mockSnapshotKV)
assert.Nil(t, err)
return mockMt, mockSnapshotKV, mockTxnKV, func() {
etcdCli.Close()
}
}
func TestMetaTable(t *testing.T) {
const (
collName = "testColl"
@ -1011,9 +1063,468 @@ func TestMetaTable(t *testing.T) {
err := mt.DeleteCredential("")
assert.Error(t, err)
})
wg.Wait()
}
func TestRbacCreateRole(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
err = mt.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: ""})
assert.NotNil(t, err)
mockTxnKV.save = func(key, value string) error {
return nil
}
err = mt.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: "role1"})
assert.Nil(t, err)
mockTxnKV.save = func(key, value string) error {
return fmt.Errorf("save error")
}
err = mt.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: "role2"})
assert.NotNil(t, err)
}
func TestRbacDropRole(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
mockTxnKV.remove = func(key string) error {
return nil
}
err = mt.DropRole(util.DefaultTenant, "role1")
assert.Nil(t, err)
mockTxnKV.remove = func(key string) error {
return fmt.Errorf("delete error")
}
err = mt.DropRole(util.DefaultTenant, "role2")
assert.NotNil(t, err)
}
func TestRbacOperateRole(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: " "}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType_AddUserToRole)
assert.NotNil(t, err)
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: " "}, milvuspb.OperateUserRoleType_AddUserToRole)
assert.NotNil(t, err)
mockTxnKV.save = func(key, value string) error {
return nil
}
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType(100))
assert.NotNil(t, err)
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType_AddUserToRole)
assert.Nil(t, err)
mockTxnKV.save = func(key, value string) error {
return fmt.Errorf("save error")
}
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType_AddUserToRole)
assert.NotNil(t, err)
mockTxnKV.remove = func(key string) error {
return nil
}
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType_RemoveUserFromRole)
assert.Nil(t, err)
mockTxnKV.remove = func(key string) error {
return fmt.Errorf("remove error")
}
err = mt.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, &milvuspb.RoleEntity{Name: "role"}, milvuspb.OperateUserRoleType_RemoveUserFromRole)
assert.NotNil(t, err)
}
func TestRbacSelectRole(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
_, err = mt.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: ""}, false)
assert.NotNil(t, err)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, fmt.Errorf("load with prefix error")
}
_, err = mt.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: "role"}, true)
assert.NotNil(t, err)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/key1", key + "/key2", key + "/a/err"}, []string{"value1", "value2", "values3"}, nil
}
mockTxnKV.load = func(key string) (string, error) {
return "", nil
}
results, _ := mt.SelectRole(util.DefaultTenant, nil, false)
assert.Equal(t, 2, len(results))
results, _ = mt.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: "role"}, false)
assert.Equal(t, 1, len(results))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, fmt.Errorf("load with prefix error")
}
_, err = mt.SelectRole(util.DefaultTenant, nil, false)
assert.NotNil(t, err)
mockTxnKV.load = func(key string) (string, error) {
return "", fmt.Errorf("load error")
}
_, err = mt.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: "role"}, false)
assert.NotNil(t, err)
roleName := "role1"
mockTxnKV.load = func(key string) (string, error) {
return "", nil
}
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/user1/" + roleName, key + "/user2/role2", key + "/user3/" + roleName, key + "/err"}, []string{"value1", "value2", "values3", "value4"}, nil
}
results, err = mt.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: roleName}, true)
assert.Nil(t, err)
assert.Equal(t, 1, len(results))
assert.Equal(t, 2, len(results[0].Users))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
if key == kvmetestore.RoleMappingPrefix {
return []string{key + "/user1/role2", key + "/user2/role2", key + "/user1/role1", key + "/user2/role1"}, []string{"value1", "value2", "values3", "value4"}, nil
} else if key == kvmetestore.RolePrefix {
return []string{key + "/role1", key + "/role2", key + "/role3"}, []string{"value1", "value2", "values3"}, nil
} else {
return []string{}, []string{}, fmt.Errorf("load with prefix error")
}
}
results, err = mt.SelectRole(util.DefaultTenant, nil, true)
assert.Nil(t, err)
assert.Equal(t, 3, len(results))
for _, result := range results {
if result.Role.Name == "role1" {
assert.Equal(t, 2, len(result.Users))
} else if result.Role.Name == "role2" {
assert.Equal(t, 2, len(result.Users))
}
}
}
func TestRbacSelectUser(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
_, err = mt.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: ""}, false)
assert.NotNil(t, err)
credentialInfo := internalpb.CredentialInfo{
EncryptedPassword: "password",
}
credentialInfoByte, _ := json.Marshal(credentialInfo)
mockTxnKV.load = func(key string) (string, error) {
return string(credentialInfoByte), nil
}
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/key1", key + "/key2"}, []string{string(credentialInfoByte), string(credentialInfoByte)}, nil
}
results, err := mt.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, false)
assert.Nil(t, err)
assert.Equal(t, 1, len(results))
results, err = mt.SelectUser(util.DefaultTenant, nil, false)
assert.Nil(t, err)
assert.Equal(t, 2, len(results))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/key1", key + "/key2", key + "/a/err"}, []string{"value1", "value2", "values3"}, nil
}
mockTxnKV.load = func(key string) (string, error) {
return string(credentialInfoByte), nil
}
results, err = mt.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, true)
assert.Nil(t, err)
assert.Equal(t, 1, len(results))
assert.Equal(t, 2, len(results[0].Roles))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
logger.Debug("simfg", zap.String("key", key))
if strings.Contains(key, kvmetestore.RoleMappingPrefix) {
if strings.Contains(key, "user1") {
return []string{key + "/role2", key + "/role1", key + "/role3"}, []string{"value1", "value4", "value2"}, nil
} else if strings.Contains(key, "user2") {
return []string{key + "/role2"}, []string{"value1"}, nil
}
return []string{}, []string{}, nil
} else if key == kvmetestore.CredentialPrefix {
return []string{key + "/user1", key + "/user2", key + "/user3"}, []string{string(credentialInfoByte), string(credentialInfoByte), string(credentialInfoByte)}, nil
} else {
return []string{}, []string{}, fmt.Errorf("load with prefix error")
}
}
results, err = mt.SelectUser(util.DefaultTenant, nil, true)
assert.Nil(t, err)
assert.Equal(t, 3, len(results))
for _, result := range results {
if result.User.Name == "user1" {
assert.Equal(t, 3, len(result.Roles))
} else if result.User.Name == "user2" {
assert.Equal(t, 1, len(result.Roles))
}
}
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, nil
}
_, err = mt.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, true)
assert.Nil(t, err)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, fmt.Errorf("load with prefix error")
}
_, err = mt.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: "user"}, true)
assert.NotNil(t, err)
_, err = mt.SelectUser(util.DefaultTenant, nil, true)
assert.NotNil(t, err)
}
func TestRbacOperatePrivilege(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
entity := &milvuspb.GrantEntity{}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
entity.ObjectName = "col1"
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
entity.Object = &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Collection.String()}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
entity.Role = &milvuspb.RoleEntity{Name: "admin"}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
entity.Grantor = &milvuspb.GrantorEntity{}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
entity.Grantor.Privilege = &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeLoad.String()}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
err = mt.OperatePrivilege(util.DefaultTenant, entity, 100)
assert.NotNil(t, err)
mockTxnKV.save = func(key, value string) error {
return nil
}
mockTxnKV.load = func(key string) (string, error) {
return "fail", fmt.Errorf("load error")
}
entity.Grantor.User = &milvuspb.UserEntity{Name: "user2"}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Revoke)
assert.NotNil(t, err)
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
mockTxnKV.load = func(key string) (string, error) {
return "unmarshal", nil
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
mockTxnKV.load = func(key string) (string, error) {
return "fail", fmt.Errorf("there is no value on key = %s", key)
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.Nil(t, err)
grantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "aaa"}, Privilege: &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeLoad.String()}},
}}
mockTxnKV.load = func(key string) (string, error) {
grantPrivilegeEntityByte, _ := proto.Marshal(grantPrivilegeEntity)
return string(grantPrivilegeEntityByte), nil
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.Nil(t, err)
entity.Grantor.Privilege = &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeRelease.String()}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Revoke)
assert.NotNil(t, err)
entity.Grantor.Privilege = &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeLoad.String()}
grantPrivilegeEntity = &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "user2"}, Privilege: &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeLoad.String()}},
}}
mockTxnKV.load = func(key string) (string, error) {
grantPrivilegeEntityByte, _ := proto.Marshal(grantPrivilegeEntity)
return string(grantPrivilegeEntityByte), nil
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.Nil(t, err)
mockTxnKV.remove = func(key string) error {
return fmt.Errorf("remove error")
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Revoke)
assert.NotNil(t, err)
mockTxnKV.remove = func(key string) error {
return nil
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Revoke)
assert.Nil(t, err)
grantPrivilegeEntity = &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "u3"}, Privilege: &milvuspb.PrivilegeEntity{Name: commonpb.ObjectPrivilege_PrivilegeInsert.String()}},
}}
mockTxnKV.load = func(key string) (string, error) {
grantPrivilegeEntityByte, _ := proto.Marshal(grantPrivilegeEntity)
return string(grantPrivilegeEntityByte), nil
}
mockTxnKV.save = func(key, value string) error {
return fmt.Errorf("save error")
}
err = mt.OperatePrivilege(util.DefaultTenant, entity, milvuspb.OperatePrivilegeType_Grant)
assert.NotNil(t, err)
}
func TestRbacSelectGrant(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
var err error
entity := &milvuspb.GrantEntity{}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
//entity.Role = &milvuspb.RoleEntity{Name: "admin"}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
mockTxnKV.load = func(key string) (string, error) {
return "unmarshal error", nil
}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
entity.Role = &milvuspb.RoleEntity{Name: "role1"}
entity.ObjectName = "col1"
entity.Object = &milvuspb.ObjectEntity{Name: "Collection"}
grantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "aaa"}, Privilege: &milvuspb.PrivilegeEntity{Name: "111"}},
{User: &milvuspb.UserEntity{Name: "bbb"}, Privilege: &milvuspb.PrivilegeEntity{Name: "222"}},
}}
grantPrivilegeEntityByte, _ := proto.Marshal(grantPrivilegeEntity)
mockTxnKV.load = func(key string) (string, error) {
return "unmarshal error", nil
}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
mockTxnKV.load = func(key string) (string, error) {
return string(grantPrivilegeEntityByte), nil
}
results, err := mt.SelectGrant(util.DefaultTenant, entity)
assert.Nil(t, err)
assert.Equal(t, 2, len(results))
mockTxnKV.load = func(key string) (string, error) {
return "", fmt.Errorf("load error")
}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
grantPrivilegeEntity2 := &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "ccc"}, Privilege: &milvuspb.PrivilegeEntity{Name: "333"}},
}}
grantPrivilegeEntityByte2, _ := proto.Marshal(grantPrivilegeEntity2)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/collection/col1", key + "/collection/col2", key + "/collection/a/col3"}, []string{string(grantPrivilegeEntityByte), string(grantPrivilegeEntityByte2), string(grantPrivilegeEntityByte2)}, nil
}
entity.ObjectName = ""
entity.Object = nil
results, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.Nil(t, err)
assert.Equal(t, 3, len(results))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return nil, nil, fmt.Errorf("load with prefix error")
}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/collection/col1"}, []string{"unmarshal error"}, nil
}
_, err = mt.SelectGrant(util.DefaultTenant, entity)
assert.NotNil(t, err)
}
func TestRbacListPolicy(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, fmt.Errorf("load with prefix err")
}
policies, err := mt.ListPolicy(util.DefaultTenant)
assert.NotNil(t, err)
assert.Equal(t, 0, len(policies))
grantPrivilegeEntity := &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "aaa"}, Privilege: &milvuspb.PrivilegeEntity{Name: "111"}},
{User: &milvuspb.UserEntity{Name: "bbb"}, Privilege: &milvuspb.PrivilegeEntity{Name: "222"}},
}}
grantPrivilegeEntityByte, _ := proto.Marshal(grantPrivilegeEntity)
grantPrivilegeEntity2 := &milvuspb.GrantPrivilegeEntity{Entities: []*milvuspb.GrantorEntity{
{User: &milvuspb.UserEntity{Name: "ccc"}, Privilege: &milvuspb.PrivilegeEntity{Name: "333"}},
}}
grantPrivilegeEntityByte2, _ := proto.Marshal(grantPrivilegeEntity2)
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/alice/collection/col1", key + "/tom/collection/col2", key + "/tom/collection/a/col2"}, []string{string(grantPrivilegeEntityByte), string(grantPrivilegeEntityByte2), string(grantPrivilegeEntityByte2)}, nil
}
policies, err = mt.ListPolicy(util.DefaultTenant)
assert.Nil(t, err)
assert.Equal(t, 3, len(policies))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/alice/collection/col1"}, []string{"unmarshal error"}, nil
}
_, err = mt.ListPolicy(util.DefaultTenant)
assert.Nil(t, err)
}
func TestRbacListUserRole(t *testing.T) {
mt, _, mockTxnKV, closeCli := generateMetaTable(t)
defer closeCli()
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{}, []string{}, fmt.Errorf("load with prefix err")
}
userRoles, err := mt.ListUserRole(util.DefaultTenant)
assert.NotNil(t, err)
assert.Equal(t, 0, len(userRoles))
mockTxnKV.loadWithPrefix = func(key string) ([]string, []string, error) {
return []string{key + "/user1/role2", key + "/user2/role2", key + "/user1/role1", key + "/user2/role1", key + "/user2/role1/a"}, []string{"value1", "value2", "values3", "value4", "value5"}, nil
}
userRoles, err = mt.ListUserRole(util.DefaultTenant)
assert.Nil(t, err)
assert.Equal(t, 4, len(userRoles))
}
func TestMetaWithTimestamp(t *testing.T) {
const (
collID1 = typeutil.UniqueID(1)

View File

@ -207,3 +207,26 @@ func (p *proxyClientManager) UpdateCredentialCache(ctx context.Context, request
}
return group.Wait()
}
func (p *proxyClientManager) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) error {
p.lock.Lock()
defer p.lock.Unlock()
if len(p.proxyClient) == 0 {
log.Warn("proxy client is empty, RefreshPrivilegeInfoCache will not send to any client")
return nil
}
group := &errgroup.Group{}
for k, v := range p.proxyClient {
k, v := k, v
group.Go(func() error {
_, err := v.RefreshPolicyInfoCache(ctx, req)
if err != nil {
return fmt.Errorf("RefreshPolicyInfoCache failed, proxyID = %d, err = %s", k, err)
}
return nil
})
}
return group.Wait()
}

View File

@ -239,3 +239,41 @@ func TestProxyClientManager_InvalidateCredentialCache(t *testing.T) {
err = pcm.InvalidateCredentialCache(ctx, nil)
assert.Error(t, err)
}
func TestProxyClientManager_RefreshPolicyInfoCache(t *testing.T) {
Params.Init()
ctx := context.Background()
core, err := NewCore(ctx, nil)
assert.Nil(t, err)
cli, err := etcd.GetEtcdClient(&Params.EtcdCfg)
assert.Nil(t, err)
defer cli.Close()
core.etcdCli = cli
pcm := newProxyClientManager(core)
ch := make(chan struct{})
pcm.helper = proxyClientManagerHelper{
afterConnect: func() { ch <- struct{}{} },
}
err = pcm.RefreshPolicyInfoCache(ctx, nil)
assert.NoError(t, err)
core.SetNewProxyClient(
func(se *sessionutil.Session) (types.Proxy, error) {
return &proxyMock{}, nil
},
)
session := &sessionutil.Session{
ServerID: 100,
Address: "localhost",
}
pcm.AddProxyClient(session)
<-ch
err = pcm.RefreshPolicyInfoCache(ctx, nil)
assert.NoError(t, err)
}

View File

@ -30,6 +30,9 @@ import (
"syscall"
"time"
"github.com/milvus-io/milvus/internal/util/errorutil"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus/internal/allocator"
@ -1245,6 +1248,11 @@ func (c *Core) Init() error {
if initError != nil {
return
}
if initError = c.initRbac(); initError != nil {
return
}
log.Debug("RootCoord init user root done")
})
if initError != nil {
log.Debug("RootCoord init error", zap.Error(initError))
@ -1264,6 +1272,45 @@ func (c *Core) initData() error {
return nil
}
func (c *Core) initRbac() (initError error) {
// create default roles, including admin, public
if initError = c.MetaTable.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: util.RoleAdmin}); initError != nil {
return
}
if initError = c.MetaTable.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: util.RolePublic}); initError != nil {
return
}
// create default rolemapping, root -> admin
if initError = c.MetaTable.OperateUserRole(util.DefaultTenant,
&milvuspb.UserEntity{Name: util.UserRoot},
&milvuspb.RoleEntity{Name: util.RoleAdmin},
milvuspb.OperateUserRoleType_AddUserToRole); initError != nil {
return
}
// grant privileges for the public role
globalPrivileges := []string{
commonpb.ObjectPrivilege_PrivilegeDescribeCollection.String(),
commonpb.ObjectPrivilege_PrivilegeShowCollections.String(),
}
for _, globalPrivilege := range globalPrivileges {
if initError = c.MetaTable.OperatePrivilege(util.DefaultTenant, &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: util.RolePublic},
Object: &milvuspb.ObjectEntity{Name: commonpb.ObjectType_Global.String()},
ObjectName: funcutil.GlobalResourceName,
Grantor: &milvuspb.GrantorEntity{
User: &milvuspb.UserEntity{Name: util.RoleAdmin},
Privilege: &milvuspb.PrivilegeEntity{Name: globalPrivilege},
},
}, milvuspb.OperatePrivilegeType_Grant); initError != nil {
return
}
}
return nil
}
func (c *Core) reSendDdMsg(ctx context.Context, force bool) error {
if !force {
flag, err := c.MetaTable.txn.Load(DDMsgSendPrefix)
@ -2850,11 +2897,21 @@ func (c *Core) CreateCredential(ctx context.Context, credInfo *internalpb.Creden
log.Debug("CreateCredential", zap.String("role", typeutil.RootCoordRole),
zap.String("username", credInfo.Username))
usersInfo, err := c.MetaTable.ListCredentialUsernames()
if err != nil {
log.Error("CreateCredential get credential username list failed", zap.String("role", typeutil.RootCoordRole),
zap.String("username", credInfo.Username), zap.Error(err))
return failStatus(commonpb.ErrorCode_CreateCredentialFailure, "CreateCredential failed, fail to get credential username list to check the user number, error: "+err.Error()), nil
}
if len(usersInfo.Usernames) >= Params.ProxyCfg.MaxUserNum {
return failStatus(commonpb.ErrorCode_CreateCredentialFailure, "unable to add user because the number of users has reached the limit"), nil
}
if cred, _ := c.MetaTable.getCredential(credInfo.Username); cred != nil {
return failStatus(commonpb.ErrorCode_CreateCredentialFailure, "user already exists:"+credInfo.Username), nil
}
// insert to db
err := c.MetaTable.AddCredential(credInfo)
err = c.MetaTable.AddCredential(credInfo)
if err != nil {
log.Error("CreateCredential save credential failed", zap.String("role", typeutil.RootCoordRole),
zap.String("username", credInfo.Username), zap.Error(err))
@ -2992,3 +3049,449 @@ func (c *Core) ListCredUsers(ctx context.Context, in *milvuspb.ListCredUsersRequ
Usernames: credInfo.Usernames,
}, nil
}
// CreateRole create role
// - check the node health
// - check if the role is existed
// - check if the role num has reached the limit
// - create the role by the metatable api
func (c *Core) CreateRole(ctx context.Context, in *milvuspb.CreateRoleRequest) (*commonpb.Status, error) {
method := "CreateRole"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
entity := in.Entity
_, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: entity.Name}, false)
if err == nil {
errMsg := "role already exists:" + entity.Name
return failStatus(commonpb.ErrorCode_CreateRoleFailure, errMsg), errors.New(errMsg)
}
if !funcutil.IsKeyNotExistError(err) {
return failStatus(commonpb.ErrorCode_CreateRoleFailure, err.Error()), err
}
results, err := c.MetaTable.SelectRole(util.DefaultTenant, nil, false)
if err != nil {
logger.Error("fail to select roles", zap.Error(err))
return failStatus(commonpb.ErrorCode_CreateRoleFailure, "fail to select roles to check the role number, error: "+err.Error()), err
}
if len(results) >= Params.ProxyCfg.MaxRoleNum {
errMsg := "unable to add role because the number of roles has reached the limit"
return failStatus(commonpb.ErrorCode_CreateRoleFailure, errMsg), errors.New(errMsg)
}
err = c.MetaTable.CreateRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: entity.Name})
if err != nil {
logger.Error("fail to create role", zap.String("role_name", entity.Name), zap.Error(err))
return failStatus(commonpb.ErrorCode_CreateRoleFailure, "CreateCollection role failed: "+err.Error()), err
}
logger.Debug(method+" success", zap.String("role_name", entity.Name))
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
metrics.RootCoordNumOfRoles.Inc()
return succStatus(), nil
}
// DropRole drop role
// - check the node health
// - check if the role name is existed
// - check if the role has some grant info
// - get all role mapping of this role
// - drop these role mappings
// - drop the role by the metatable api
func (c *Core) DropRole(ctx context.Context, in *milvuspb.DropRoleRequest) (*commonpb.Status, error) {
method := "DropRole"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if _, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: in.RoleName}, false); err != nil {
logger.Error("the role isn't existed", zap.String("role_name", in.RoleName), zap.Error(err))
return failStatus(commonpb.ErrorCode_DropRoleFailure, fmt.Sprintf("the role isn't existed, role name: %s", in.RoleName)), err
}
grantEntities, err := c.MetaTable.SelectGrant(util.DefaultTenant, &milvuspb.GrantEntity{
Role: &milvuspb.RoleEntity{Name: in.RoleName},
})
if len(grantEntities) != 0 {
errMsg := "fail to drop the role that it has privileges. Use REVOKE API to revoke privileges"
logger.Error(errMsg, zap.String("role_name", in.RoleName), zap.Error(err))
return failStatus(commonpb.ErrorCode_DropRoleFailure, errMsg), errors.New(errMsg)
}
roleResults, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: in.RoleName}, true)
if err != nil {
errMsg := "fail to select a role by role name"
logger.Error("fail to select a role by role name", zap.String("role_name", in.RoleName), zap.Error(err))
return failStatus(commonpb.ErrorCode_DropRoleFailure, errMsg), err
}
logger.Debug("role to user info", zap.Int("counter", len(roleResults)))
for _, roleResult := range roleResults {
for index, userEntity := range roleResult.Users {
if err = c.MetaTable.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: userEntity.Name}, &milvuspb.RoleEntity{Name: roleResult.Role.Name}, milvuspb.OperateUserRoleType_RemoveUserFromRole); err != nil {
errMsg := "fail to remove user from role"
logger.Error(errMsg, zap.String("role_name", roleResult.Role.Name), zap.String("username", userEntity.Name), zap.Int("current_index", index), zap.Error(err))
return failStatus(commonpb.ErrorCode_OperateUserRoleFailure, errMsg), err
}
}
}
if err = c.MetaTable.DropRole(util.DefaultTenant, in.RoleName); err != nil {
errMsg := "fail to drop the role"
logger.Error(errMsg, zap.String("role_name", in.RoleName), zap.Error(err))
return failStatus(commonpb.ErrorCode_DropRoleFailure, errMsg), err
}
logger.Debug(method+" success", zap.String("role_name", in.RoleName))
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
metrics.RootCoordNumOfRoles.Dec()
return succStatus(), nil
}
// OperateUserRole operate the relationship between a user and a role
// - check the node health
// - check if the role is valid
// - check if the user is valid
// - operate the user-role by the metatable api
// - update the policy cache
func (c *Core) OperateUserRole(ctx context.Context, in *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
method := "OperateUserRole-" + in.Type.String()
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if _, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: in.RoleName}, false); err != nil {
errMsg := "fail to check the role name"
logger.Error(errMsg, zap.String("role_name", in.RoleName), zap.Error(err))
return failStatus(commonpb.ErrorCode_OperateUserRoleFailure, errMsg), err
}
if _, err := c.MetaTable.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: in.Username}, false); err != nil {
errMsg := "fail to check the username"
logger.Error(errMsg, zap.String("username", in.Username), zap.Error(err))
return failStatus(commonpb.ErrorCode_OperateUserRoleFailure, errMsg), err
}
if err := c.MetaTable.OperateUserRole(util.DefaultTenant, &milvuspb.UserEntity{Name: in.Username}, &milvuspb.RoleEntity{Name: in.RoleName}, in.Type); err != nil {
errMsg := "fail to operate user to role"
logger.Error(errMsg, zap.String("role_name", in.RoleName), zap.String("username", in.Username), zap.Error(err))
return failStatus(commonpb.ErrorCode_OperateUserRoleFailure, errMsg), err
}
var opType int32
if in.Type == milvuspb.OperateUserRoleType_AddUserToRole {
opType = int32(typeutil.CacheAddUserToRole)
} else if in.Type == milvuspb.OperateUserRoleType_RemoveUserFromRole {
opType = int32(typeutil.CacheRemoveUserFromRole)
}
if err := c.proxyClientManager.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
OpType: opType,
OpKey: funcutil.EncodeUserRoleCache(in.Username, in.RoleName),
}); err != nil {
return failStatus(commonpb.ErrorCode_OperateUserRoleFailure, err.Error()), err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return succStatus(), nil
}
// SelectRole select role
// - check the node health
// - check if the role is valid when this param is provided
// - select role by the metatable api
func (c *Core) SelectRole(ctx context.Context, in *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) {
method := "SelectRole"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return &milvuspb.SelectRoleResponse{Status: errorutil.UnhealthyStatus(code)}, errorutil.UnhealthyError()
}
if in.Role != nil {
if _, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: in.Role.Name}, false); err != nil {
errMsg := "fail to select the role to check the role name"
logger.Error(errMsg, zap.String("role_name", in.Role.Name), zap.Error(err))
return &milvuspb.SelectRoleResponse{
Status: failStatus(commonpb.ErrorCode_SelectRoleFailure, errMsg),
}, err
}
}
roleResults, err := c.MetaTable.SelectRole(util.DefaultTenant, in.Role, in.IncludeUserInfo)
if err != nil {
errMsg := "fail to select the role"
logger.Error(errMsg, zap.Error(err))
return &milvuspb.SelectRoleResponse{
Status: failStatus(commonpb.ErrorCode_SelectRoleFailure, errMsg),
}, err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return &milvuspb.SelectRoleResponse{
Status: succStatus(),
Results: roleResults,
}, nil
}
// SelectUser select user
// - check the node health
// - check if the user is valid when this param is provided
// - select user by the metatable api
func (c *Core) SelectUser(ctx context.Context, in *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) {
method := "SelectUser"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return &milvuspb.SelectUserResponse{Status: errorutil.UnhealthyStatus(code)}, errorutil.UnhealthyError()
}
if in.User != nil {
if _, err := c.MetaTable.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: in.User.Name}, false); err != nil {
errMsg := "fail to select the user to check the username"
logger.Error(errMsg, zap.String("username", in.User.Name), zap.Error(err))
return &milvuspb.SelectUserResponse{
Status: failStatus(commonpb.ErrorCode_SelectUserFailure, errMsg),
}, err
}
}
userResults, err := c.MetaTable.SelectUser(util.DefaultTenant, in.User, in.IncludeRoleInfo)
if err != nil {
errMsg := "fail to select the user"
log.Error(errMsg, zap.Error(err))
return &milvuspb.SelectUserResponse{
Status: failStatus(commonpb.ErrorCode_SelectUserFailure, errMsg),
}, err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return &milvuspb.SelectUserResponse{
Status: succStatus(),
Results: userResults,
}, nil
}
func (c *Core) isValidRole(entity *milvuspb.RoleEntity) error {
if entity == nil {
return fmt.Errorf("the role entity is nil")
}
if entity.Name == "" {
return fmt.Errorf("the name in the role entity is empty")
}
if _, err := c.MetaTable.SelectRole(util.DefaultTenant, &milvuspb.RoleEntity{Name: entity.Name}, false); err != nil {
return err
}
return nil
}
func (c *Core) isValidObject(entity *milvuspb.ObjectEntity) error {
if entity == nil {
return fmt.Errorf("the object entity is nil")
}
if _, ok := commonpb.ObjectType_value[entity.Name]; !ok {
return fmt.Errorf("the object type in the object entity is invalid, current value: %s", entity.Name)
}
return nil
}
func (c *Core) isValidGrantor(entity *milvuspb.GrantorEntity, object string) error {
if entity == nil {
return fmt.Errorf("the grantor entity is nil")
}
if entity.User == nil {
return fmt.Errorf("the user entity in the grantor entity is nil")
}
if entity.User.Name == "" {
return fmt.Errorf("the name in the user entity of the grantor entity is empty")
}
if _, err := c.MetaTable.SelectUser(util.DefaultTenant, &milvuspb.UserEntity{Name: entity.GetUser().Name}, false); err != nil {
return err
}
if entity.Privilege == nil {
return fmt.Errorf("the privilege entity in the grantor entity is nil")
}
if privilegeName := util.PrivilegeNameForDb(entity.Privilege.Name); privilegeName == "" {
return fmt.Errorf("the privilege name in the privilege entity is invalid, current value: %s", entity.Privilege.Name)
}
privileges, ok := util.GetObjectPrivileges()[object]
if !ok {
return fmt.Errorf("the object type is invalid, current value: %s", object)
}
for _, privilege := range privileges {
if privilege == entity.Privilege.Name {
return nil
}
}
return fmt.Errorf("the privilege name is invalid, current value: %s", entity.Privilege.Name)
}
// OperatePrivilege operate the privilege, including grant and revoke
// - check the node health
// - check if the operating type is valid
// - check if the entity is nil
// - check if the params, including the resource entity, the principal entity, the grantor entity, is valid
// - operate the privilege by the metatable api
// - update the policy cache
func (c *Core) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) {
method := "OperatePrivilege"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return errorutil.UnhealthyStatus(code), errorutil.UnhealthyError()
}
if in.Type != milvuspb.OperatePrivilegeType_Grant && in.Type != milvuspb.OperatePrivilegeType_Revoke {
errMsg := fmt.Sprintf("invalid operate privilege type, current type: %s, valid value: [%s, %s]", in.Type, milvuspb.OperatePrivilegeType_Grant, milvuspb.OperatePrivilegeType_Revoke)
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, errMsg), errors.New(errMsg)
}
if in.Entity == nil {
errMsg := "the grant entity in the request is nil"
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, errMsg), errors.New(errMsg)
}
if err := c.isValidObject(in.Entity.Object); err != nil {
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, err.Error()), err
}
if err := c.isValidRole(in.Entity.Role); err != nil {
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, err.Error()), err
}
if err := c.isValidGrantor(in.Entity.Grantor, in.Entity.Object.Name); err != nil {
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, err.Error()), err
}
logger.Debug("before PrivilegeNameForDb", zap.String("privilege", in.Entity.Grantor.Privilege.Name))
in.Entity.Grantor.Privilege.Name = util.PrivilegeNameForDb(in.Entity.Grantor.Privilege.Name)
logger.Debug("after PrivilegeNameForDb", zap.String("privilege", in.Entity.Grantor.Privilege.Name))
if in.Entity.Object.Name == commonpb.ObjectType_Global.String() {
in.Entity.ObjectName = funcutil.GlobalResourceName
}
if err := c.MetaTable.OperatePrivilege(util.DefaultTenant, in.Entity, in.Type); err != nil {
errMsg := "fail to operate the privilege"
logger.Error(errMsg, zap.Error(err))
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, errMsg), err
}
var opType int32
if in.Type == milvuspb.OperatePrivilegeType_Grant {
opType = int32(typeutil.CacheGrantPrivilege)
} else if in.Type == milvuspb.OperatePrivilegeType_Revoke {
opType = int32(typeutil.CacheRevokePrivilege)
}
if err := c.proxyClientManager.RefreshPolicyInfoCache(ctx, &proxypb.RefreshPolicyInfoCacheRequest{
OpType: opType,
OpKey: funcutil.PolicyForPrivilege(in.Entity.Role.Name, in.Entity.Object.Name, in.Entity.ObjectName, in.Entity.Grantor.Privilege.Name),
}); err != nil {
return failStatus(commonpb.ErrorCode_OperatePrivilegeFailure, err.Error()), err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return succStatus(), nil
}
// SelectGrant select grant
// - check the node health
// - check if the principal entity is valid
// - check if the resource entity which is provided by the user is valid
// - select grant by the metatable api
func (c *Core) SelectGrant(ctx context.Context, in *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) {
method := "SelectGrant"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return &milvuspb.SelectGrantResponse{
Status: errorutil.UnhealthyStatus(code),
}, errorutil.UnhealthyError()
}
if in.Entity == nil {
errMsg := "the grant entity in the request is nil"
return &milvuspb.SelectGrantResponse{
Status: failStatus(commonpb.ErrorCode_SelectGrantFailure, errMsg),
}, errors.New(errMsg)
}
if err := c.isValidRole(in.Entity.Role); err != nil {
return &milvuspb.SelectGrantResponse{
Status: failStatus(commonpb.ErrorCode_SelectGrantFailure, err.Error()),
}, err
}
if in.Entity.Object != nil {
if err := c.isValidObject(in.Entity.Object); err != nil {
return &milvuspb.SelectGrantResponse{
Status: failStatus(commonpb.ErrorCode_SelectGrantFailure, err.Error()),
}, err
}
}
grantEntities, err := c.MetaTable.SelectGrant(util.DefaultTenant, in.Entity)
if err != nil {
errMsg := "fail to select the grant"
logger.Error(errMsg, zap.Error(err))
return &milvuspb.SelectGrantResponse{
Status: failStatus(commonpb.ErrorCode_SelectGrantFailure, errMsg),
}, err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return &milvuspb.SelectGrantResponse{
Status: succStatus(),
Entities: grantEntities,
}, nil
}
func (c *Core) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) {
method := "PolicyList"
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc()
tr := timerecord.NewTimeRecorder(method)
logger.Debug(method, zap.Any("in", in))
if code, ok := c.checkHealthy(); !ok {
return &internalpb.ListPolicyResponse{
Status: errorutil.UnhealthyStatus(code),
}, errorutil.UnhealthyError()
}
policies, err := c.MetaTable.ListPolicy(util.DefaultTenant)
if err != nil {
return &internalpb.ListPolicyResponse{
Status: failStatus(commonpb.ErrorCode_ListPolicyFailure, "fail to list policy"),
}, err
}
userRoles, err := c.MetaTable.ListUserRole(util.DefaultTenant)
if err != nil {
return &internalpb.ListPolicyResponse{
Status: failStatus(commonpb.ErrorCode_ListPolicyFailure, "fail to list user-role"),
}, err
}
logger.Debug(method + " success")
metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc()
metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds()))
return &internalpb.ListPolicyResponse{
Status: succStatus(),
PolicyInfos: policies,
UserRoles: userRoles,
}, nil
}

View File

@ -146,6 +146,12 @@ func (p *proxyMock) InvalidateCredentialCache(ctx context.Context, request *prox
}, nil
}
func (p *proxyMock) RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error) {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
}, nil
}
type dataMock struct {
types.DataCoord
randVal int
@ -790,6 +796,7 @@ func TestRootCoordInitData(t *testing.T) {
return fmt.Errorf("save error")
},
remove: func(key string) error { return txnKV.Remove(key) },
load: func(key string) (string, error) { return txnKV.Load(key) },
}
//mt.txn = mockTxnKV
mt.catalog = &kvmetestore.Catalog{Txn: mockTxnKV, Snapshot: snapshotKV}
@ -3592,3 +3599,61 @@ func TestCore_GetIndexState(t *testing.T) {
assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.GetErrorCode())
})
}
func TestCore_Rbac(t *testing.T) {
ctx := context.Background()
c := &Core{
ctx: ctx,
}
// not healthy.
c.stateCode.Store(internalpb.StateCode_Abnormal)
{
resp, err := c.CreateRole(ctx, &milvuspb.CreateRoleRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
}
{
resp, err := c.DropRole(ctx, &milvuspb.DropRoleRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
}
{
resp, err := c.OperateUserRole(ctx, &milvuspb.OperateUserRoleRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
}
{
resp, err := c.SelectRole(ctx, &milvuspb.SelectRoleRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
}
{
resp, err := c.SelectUser(ctx, &milvuspb.SelectUserRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
}
{
resp, err := c.OperatePrivilege(ctx, &milvuspb.OperatePrivilegeRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode)
}
{
resp, err := c.SelectGrant(ctx, &milvuspb.SelectGrantRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
}
{
resp, err := c.ListPolicy(ctx, &internalpb.ListPolicyRequest{})
assert.NotNil(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
}
}

View File

@ -20,6 +20,9 @@ import (
"encoding/json"
"fmt"
"github.com/milvus-io/milvus/internal/log"
"go.uber.org/zap"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/metastore/model"
@ -30,6 +33,8 @@ import (
"github.com/milvus-io/milvus/internal/util/typeutil"
)
var logger = log.L().WithOptions(zap.Fields(zap.String("role", typeutil.RootCoordRole)))
// EqualKeyPairArray check whether 2 KeyValuePairs are equal
func EqualKeyPairArray(p1 []*commonpb.KeyValuePair, p2 []*commonpb.KeyValuePair) bool {
if len(p1) != len(p2) {

View File

@ -686,6 +686,15 @@ type RootCoord interface {
ListCredUsers(ctx context.Context, req *milvuspb.ListCredUsersRequest) (*milvuspb.ListCredUsersResponse, error)
// GetCredential get credential by username
GetCredential(ctx context.Context, req *rootcoordpb.GetCredentialRequest) (*rootcoordpb.GetCredentialResponse, error)
CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error)
DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error)
OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error)
SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error)
SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error)
OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error)
SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error)
ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error)
}
// RootCoordComponent is used by grpc server of RootCoord
@ -775,6 +784,8 @@ type Proxy interface {
SendSearchResult(ctx context.Context, req *internalpb.SearchResults) (*commonpb.Status, error)
SendRetrieveResult(ctx context.Context, req *internalpb.RetrieveResults) (*commonpb.Status, error)
RefreshPolicyInfoCache(ctx context.Context, req *proxypb.RefreshPolicyInfoCacheRequest) (*commonpb.Status, error)
}
// ProxyComponent defines the interface of proxy component.
@ -1196,6 +1207,14 @@ type ProxyComponent interface {
DeleteCredential(ctx context.Context, req *milvuspb.DeleteCredentialRequest) (*commonpb.Status, error)
// ListCredUsers list all usernames
ListCredUsers(ctx context.Context, req *milvuspb.ListCredUsersRequest) (*milvuspb.ListCredUsersResponse, error)
CreateRole(ctx context.Context, req *milvuspb.CreateRoleRequest) (*commonpb.Status, error)
DropRole(ctx context.Context, req *milvuspb.DropRoleRequest) (*commonpb.Status, error)
OperateUserRole(ctx context.Context, req *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error)
SelectRole(ctx context.Context, req *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error)
SelectUser(ctx context.Context, req *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error)
OperatePrivilege(ctx context.Context, req *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error)
SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error)
}
// QueryNode is the interface `querynode` package implements

View File

@ -16,6 +16,8 @@
package util
import "github.com/milvus-io/milvus/internal/proto/commonpb"
// Meta Prefix consts
const (
SegmentMetaPrefix = "queryCoord-segmentMeta"
@ -29,4 +31,132 @@ const (
CredentialSeperator = ":"
UserRoot = "root"
DefaultRootPassword = "Milvus"
DefaultTenant = ""
RoleAdmin = "admin"
RolePublic = "public"
)
// ObjectPrivilegeAPI privilege name for using api
type ObjectPrivilegeAPI int32
func (o ObjectPrivilegeAPI) String() string {
switch o {
case All:
return "All"
case CreateCollection:
return "CreateCollection"
case DropCollection:
return "DropCollection"
case DescribeCollection:
return "DescribeCollection"
case ShowCollections:
return "ShowCollections"
case Load:
return "Load"
case Release:
return "Release"
case Compact:
return "Compact"
case Insert:
return "Insert"
case Delete:
return "Delete"
default:
return ""
}
}
const (
All ObjectPrivilegeAPI = iota
CreateCollection
DropCollection
DescribeCollection
ShowCollections
Load
Release
Compact
Insert
Delete
None = 999
)
func GetObjectPrivilegeFromName(name string) ObjectPrivilegeAPI {
switch name {
case All.String():
return All
case CreateCollection.String():
return CreateCollection
case DropCollection.String():
return DropCollection
case DescribeCollection.String():
return DescribeCollection
case ShowCollections.String():
return ShowCollections
case Load.String():
return Load
case Release.String():
return Release
case Compact.String():
return Compact
case Insert.String():
return Insert
case Delete.String():
return Delete
default:
return None
}
}
// StringSet convert array to map for conveniently check if the array contains an element
func StringSet(strings []string) map[string]struct{} {
stringsMap := make(map[string]struct{})
for _, str := range strings {
stringsMap[str] = struct{}{}
}
return stringsMap
}
func StringList(stringMap map[string]struct{}) []string {
strs := make([]string, 0, len(stringMap))
for k := range stringMap {
strs = append(strs, k)
}
return strs
}
// GetObjectPrivileges get the mapping between object types and privileges. This kind of data is constant and doesn't support to CRUD
func GetObjectPrivileges() map[string][]string {
return map[string][]string{
commonpb.ObjectType_Collection.String(): {
Load.String(),
Release.String(),
Compact.String(),
Insert.String(),
Delete.String(),
},
commonpb.ObjectType_Global.String(): {
All.String(),
CreateCollection.String(),
DropCollection.String(),
DescribeCollection.String(),
ShowCollections.String(),
},
}
}
func PrivilegeNameForAPI(name string) string {
index, ok := commonpb.ObjectPrivilege_value[name]
if !ok {
return ""
}
return ObjectPrivilegeAPI(index).String()
}
func PrivilegeNameForDb(name string) string {
o := GetObjectPrivilegeFromName(name)
if o == None {
return ""
}
return commonpb.ObjectPrivilege_name[int32(o)]
}

View File

@ -1,8 +1,13 @@
package errorutil
import (
"fmt"
"errors"
"strings"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"fmt"
)
// ErrorList for print error log
@ -25,3 +30,18 @@ func (el ErrorList) Error() string {
}
return builder.String()
}
func UnhealthyStatus(code internalpb.StateCode) *commonpb.Status {
return &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
Reason: "proxy not healthy, StateCode=" + internalpb.StateCode_name[int32(code)],
}
}
func UnhealthyError() error {
return errors.New("unhealthy node")
}
func PermissionDenyError() error {
return errors.New("permission deny")
}

View File

@ -31,6 +31,8 @@ import (
"strings"
"time"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"go.uber.org/zap"
"github.com/go-basic/ipv4"
@ -359,3 +361,42 @@ func IsGrpcErr(err error) bool {
err = errors.Unwrap(err)
}
}
func IsEmptyString(str string) bool {
return strings.TrimSpace(str) == ""
}
func HandleTenantForEtcdKey(prefix string, tenant string, key string) string {
res := prefix
if tenant != "" {
res += "/" + tenant
}
if key != "" {
res += "/" + key
}
return res
}
func IsRevoke(operateType milvuspb.OperatePrivilegeType) bool {
return operateType == milvuspb.OperatePrivilegeType_Revoke
}
func IsGrant(operateType milvuspb.OperatePrivilegeType) bool {
return operateType == milvuspb.OperatePrivilegeType_Grant
}
// IsKeyNotExistError Judging by the error message whether the key does not exist or not for the ectd server
func IsKeyNotExistError(err error) bool {
return strings.Contains(err.Error(), "there is no value on key")
}
func EncodeUserRoleCache(user string, role string) string {
return fmt.Sprintf("%s/%s", user, role)
}
func DecodeUserRoleCache(cache string) (string, string) {
index := strings.LastIndex(cache, "/")
user := cache[:index]
role := cache[index+1:]
return user, role
}

View File

@ -503,3 +503,43 @@ func TestIsGrpcErr(t *testing.T) {
assert.True(t, IsGrpcErr(errWrap))
})
}
func TestIsEmptyString(t *testing.T) {
assert.Equal(t, IsEmptyString(""), true)
assert.Equal(t, IsEmptyString(" "), true)
assert.Equal(t, IsEmptyString("hello"), false)
}
func TestHandleTenantForEtcdKey(t *testing.T) {
assert.Equal(t, "a/b/c", HandleTenantForEtcdKey("a", "b", "c"))
assert.Equal(t, "a/b", HandleTenantForEtcdKey("a", "", "b"))
assert.Equal(t, "a/b", HandleTenantForEtcdKey("a", "b", ""))
assert.Equal(t, "a", HandleTenantForEtcdKey("a", "", ""))
}
func TestIsRevoke(t *testing.T) {
assert.Equal(t, true, IsRevoke(milvuspb.OperatePrivilegeType_Revoke))
assert.Equal(t, false, IsRevoke(milvuspb.OperatePrivilegeType_Grant))
}
func TestIsGrant(t *testing.T) {
assert.Equal(t, true, IsGrant(milvuspb.OperatePrivilegeType_Grant))
assert.Equal(t, false, IsGrant(milvuspb.OperatePrivilegeType_Revoke))
}
func TestIsKeyNotExistError(t *testing.T) {
assert.Equal(t, true, IsKeyNotExistError(fmt.Errorf("there is no value on key = %s", "foo")))
assert.Equal(t, false, IsKeyNotExistError(fmt.Errorf("err: key = %s", "fooo")))
}
func TestUserRoleCache(t *testing.T) {
user, role := "foo", "root"
cache := EncodeUserRoleCache(user, role)
assert.Equal(t, fmt.Sprintf("%s/%s", user, role), cache)
u, r := DecodeUserRoleCache(cache)
assert.Equal(t, user, u)
assert.Equal(t, role, r)
}

View File

@ -0,0 +1,71 @@
package funcutil
import (
"fmt"
"github.com/golang/protobuf/descriptor"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"go.uber.org/zap"
"google.golang.org/protobuf/reflect/protoreflect"
)
const (
GlobalResourceName = "*"
)
func GetVersion(m proto.GeneratedMessage) (string, error) {
md, _ := descriptor.MessageDescriptorProto(m)
if md == nil {
log.Error("MessageDescriptorProto result is nil")
return "", fmt.Errorf("MessageDescriptorProto result is nil")
}
extObj, err := proto.GetExtension(md.Options, milvuspb.E_MilvusExtObj)
if err != nil {
log.Error("GetExtension fail", zap.Error(err))
return "", err
}
version := extObj.(*milvuspb.MilvusExt).Version
log.Debug("GetVersion success", zap.String("version", version))
return version, nil
}
func GetPrivilegeExtObj(m proto.GeneratedMessage) (commonpb.PrivilegeExt, error) {
_, md := descriptor.MessageDescriptorProto(m)
if md == nil {
log.Error("MessageDescriptorProto result is nil")
return commonpb.PrivilegeExt{}, fmt.Errorf("MessageDescriptorProto result is nil")
}
extObj, err := proto.GetExtension(md.Options, commonpb.E_PrivilegeExtObj)
if err != nil {
log.Error("GetExtension fail", zap.Error(err))
return commonpb.PrivilegeExt{}, err
}
privilegeExt := extObj.(*commonpb.PrivilegeExt)
log.Debug("GetPrivilegeExtObj success", zap.String("resource_type", privilegeExt.ObjectType.String()), zap.String("resource_privilege", privilegeExt.ObjectPrivilege.String()))
return commonpb.PrivilegeExt{
ObjectType: privilegeExt.ObjectType,
ObjectPrivilege: privilegeExt.ObjectPrivilege,
ObjectNameIndex: privilegeExt.ObjectNameIndex,
}, nil
}
func GetResourceName(m proto.GeneratedMessage, index int32) string {
if index <= 0 {
return GlobalResourceName
}
msg := proto.MessageReflect(proto.MessageV1(m))
msgDesc := msg.Descriptor()
return msg.Get(msgDesc.Fields().ByNumber(protoreflect.FieldNumber(index))).String()
}
func PolicyForPrivilege(roleName string, objectType string, objectName string, privilege string) string {
return fmt.Sprintf(`{"PType":"p","V0":"%s","V1":"%s","V2":"%s"}`, roleName, PolicyForResource(objectType, objectName), privilege)
}
func PolicyForResource(objectType string, objectName string) string {
return fmt.Sprintf("%s-%s", objectType, objectName)
}

View File

@ -0,0 +1,65 @@
package funcutil
import (
"testing"
"github.com/milvus-io/milvus/internal/proto/commonpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
"github.com/stretchr/testify/assert"
)
func Test_GetVersion(t *testing.T) {
request := &milvuspb.HasCollectionRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Undefined,
MsgID: 123,
},
DbName: "test",
CollectionName: "col1",
}
str, err := GetVersion(request)
assert.Nil(t, err)
assert.Equal(t, str, "2.1.0")
request2 := &commonpb.MsgBase{}
_, err = GetVersion(request2)
assert.NotNil(t, err)
}
func Test_GetPrivilegeExtObj(t *testing.T) {
request := &milvuspb.LoadCollectionRequest{
DbName: "test",
CollectionName: "col1",
}
privilegeExt, err := GetPrivilegeExtObj(request)
assert.Nil(t, err)
assert.Equal(t, commonpb.ObjectType_Collection, privilegeExt.ObjectType)
assert.Equal(t, commonpb.ObjectPrivilege_PrivilegeLoad, privilegeExt.ObjectPrivilege)
assert.Equal(t, int32(3), privilegeExt.ObjectNameIndex)
request2 := &milvuspb.CreatePartitionRequest{}
_, err = GetPrivilegeExtObj(request2)
assert.NotNil(t, err)
}
func Test_GetResourceName(t *testing.T) {
request := &milvuspb.HasCollectionRequest{
DbName: "test",
CollectionName: "col1",
}
assert.Equal(t, "*", GetResourceName(request, 0))
assert.Equal(t, "col1", GetResourceName(request, 3))
}
func Test_PolicyForPrivilege(t *testing.T) {
assert.Equal(t,
`{"PType":"p","V0":"admin","V1":"COLLECTION-col1","V2":"ALL"}`,
PolicyForPrivilege("admin", "COLLECTION", "col1", "ALL"))
}
func Test_PolicyForResource(t *testing.T) {
assert.Equal(t,
`COLLECTION-col1`,
PolicyForResource("COLLECTION", "col1"))
}

View File

@ -9,6 +9,9 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
//go:build linux
// +build linux
package metricsinfo
import (

View File

@ -57,10 +57,6 @@ func (m *GrpcRootCoordClient) SelectUser(ctx context.Context, in *milvuspb.Selec
return &milvuspb.SelectUserResponse{}, m.Err
}
func (m *GrpcRootCoordClient) SelectResource(ctx context.Context, in *milvuspb.SelectResourceRequest, opts ...grpc.CallOption) (*milvuspb.SelectResourceResponse, error) {
return &milvuspb.SelectResourceResponse{}, m.Err
}
func (m *GrpcRootCoordClient) OperatePrivilege(ctx context.Context, in *milvuspb.OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
return &commonpb.Status{}, m.Err
}

View File

@ -433,6 +433,8 @@ type proxyConfig struct {
MaxShardNum int32
MaxDimension int64
GinLogging bool
MaxUserNum int
MaxRoleNum int
// required from QueryCoord
SearchResultChannelNames []string
@ -460,6 +462,8 @@ func (p *proxyConfig) init(base *BaseTable) {
p.initMaxTaskNum()
p.initGinLogging()
p.initMaxUserNum()
p.initMaxRoleNum()
}
// InitAlias initialize Alias member.
@ -560,6 +564,24 @@ func (p *proxyConfig) GetNodeID() UniqueID {
return 0
}
func (p *proxyConfig) initMaxUserNum() {
str := p.Base.LoadWithDefault("proxy.maxUserNum", "100")
maxUserNum, err := strconv.ParseInt(str, 10, 64)
if err != nil {
panic(err)
}
p.MaxUserNum = int(maxUserNum)
}
func (p *proxyConfig) initMaxRoleNum() {
str := p.Base.LoadWithDefault("proxy.maxRoleNum", "10")
maxRoleNum, err := strconv.ParseInt(str, 10, 64)
if err != nil {
panic(err)
}
p.MaxRoleNum = int(maxRoleNum)
}
///////////////////////////////////////////////////////////////////////////////
// --- querycoord ---
type queryCoordConfig struct {

View File

@ -200,6 +200,16 @@ func TestComponentParam(t *testing.T) {
Params.Base.Save("proxy.maxTaskNum", "-asdf")
Params.initMaxTaskNum()
})
shouldPanic(t, "proxy.maxUserNum", func() {
Params.Base.Save("proxy.maxUserNum", "abc")
Params.initMaxUserNum()
})
shouldPanic(t, "proxy.maxRoleNum", func() {
Params.Base.Save("proxy.maxRoleNum", "abc")
Params.initMaxRoleNum()
})
})
t.Run("test queryNodeConfig", func(t *testing.T) {

View File

@ -0,0 +1,15 @@
package typeutil
type CacheOpType int32
const (
CacheAddUserToRole CacheOpType = iota + 1
CacheRemoveUserFromRole
CacheGrantPrivilege
CacheRevokePrivilege
)
type CacheOp struct {
OpType CacheOpType
OpKey string
}

View File

@ -47,3 +47,8 @@ func After(str string, sub string) string {
}
return str[adjustedPos:]
}
// AfterN Split slices After(str) into all substrings separated by sep
func AfterN(str string, sub string, sep string) []string {
return strings.Split(After(str, sub), sep)
}