diff --git a/go.mod b/go.mod index f9c9be1d2b..c55449fb8f 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index a67da9c7c0..ceb507f187 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/core/src/pb/common.pb.cc b/internal/core/src/pb/common.pb.cc index a1ffc0b277..73f7970b22 100644 --- a/internal/core/src/pb/common.pb.cc +++ b/internal/core/src/pb/common.pb.cc @@ -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(reinterpret_cast(&resource_name_index_) - - reinterpret_cast(&resource_type_)) + sizeof(resource_name_index_)); + ::memcpy(&object_type_, &from.object_type_, + static_cast(reinterpret_cast(&object_name_index_) - + reinterpret_cast(&object_type_)) + sizeof(object_name_index_)); // @@protoc_insertion_point(copy_constructor:milvus.proto.common.PrivilegeExt) } void PrivilegeExt::SharedCtor() { - ::memset(&resource_type_, 0, static_cast( - reinterpret_cast(&resource_name_index_) - - reinterpret_cast(&resource_type_)) + sizeof(resource_name_index_)); + ::memset(&object_type_, 0, static_cast( + reinterpret_cast(&object_name_index_) - + reinterpret_cast(&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( - reinterpret_cast(&resource_name_index_) - - reinterpret_cast(&resource_type_)) + sizeof(resource_name_index_)); + ::memset(&object_type_, 0, static_cast( + reinterpret_cast(&object_name_index_) - + reinterpret_cast(&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 { diff --git a/internal/core/src/pb/common.pb.h b/internal/core/src/pb/common.pb.h index af72269361..644dce6fc8 100644 --- a/internal/core/src/pb/common.pb.h +++ b/internal/core/src/pb/common.pb.h @@ -478,62 +478,63 @@ inline bool ImportState_Parse( return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( 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 -inline const std::string& ResourceType_Name(T enum_t_value) { - static_assert(::std::is_same::value || +inline const std::string& ObjectType_Name(T enum_t_value) { + static_assert(::std::is_same::value || ::std::is_integral::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_descriptor(), name, value); +inline bool ObjectType_Parse( + const std::string& name, ObjectType* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( + 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 -inline const std::string& ResourcePrivilege_Name(T enum_t_value) { - static_assert(::std::is_same::value || +inline const std::string& ObjectPrivilege_Name(T enum_t_value) { + static_assert(::std::is_same::value || ::std::is_integral::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_descriptor(), name, value); +inline bool ObjectPrivilege_Parse( + const std::string& name, ObjectPrivilege* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( + 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 diff --git a/internal/datacoord/mock_test.go b/internal/datacoord/mock_test.go index 89bdaba3ec..9b6e88bbf2 100644 --- a/internal/datacoord/mock_test.go +++ b/internal/datacoord/mock_test.go @@ -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 { } diff --git a/internal/distributed/proxy/client/client_test.go b/internal/distributed/proxy/client/client_test.go index 481163864a..1cd8469088 100644 --- a/internal/distributed/proxy/client/client_test.go +++ b/internal/distributed/proxy/client/client_test.go @@ -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) diff --git a/internal/distributed/proxy/service.go b/internal/distributed/proxy/service.go index 37ff27dc7b..54668fe994 100644 --- a/internal/distributed/proxy/service.go +++ b/internal/distributed/proxy/service.go @@ -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) } diff --git a/internal/distributed/proxy/service_test.go b/internal/distributed/proxy/service_test.go index ea333af812..8063a53740 100644 --- a/internal/distributed/proxy/service_test.go +++ b/internal/distributed/proxy/service_test.go @@ -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) diff --git a/internal/distributed/rootcoord/client/client.go b/internal/distributed/rootcoord/client/client.go index 1682c2c6bd..9ef618ccb5 100644 --- a/internal/distributed/rootcoord/client/client.go +++ b/internal/distributed/rootcoord/client/client.go @@ -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) { diff --git a/internal/distributed/rootcoord/client/client_test.go b/internal/distributed/rootcoord/client/client_test.go index 295415a477..fd0ac60103 100644 --- a/internal/distributed/rootcoord/client/client_test.go +++ b/internal/distributed/rootcoord/client/client_test.go @@ -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() diff --git a/internal/distributed/rootcoord/service.go b/internal/distributed/rootcoord/service.go index 03274911e2..d2ff85a74a 100644 --- a/internal/distributed/rootcoord/service.go +++ b/internal/distributed/rootcoord/service.go @@ -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) } diff --git a/internal/log/log_test.go b/internal/log/log_test.go index e9ccb3199c..f975e883e4 100644 --- a/internal/log/log_test.go +++ b/internal/log/log_test.go @@ -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()) diff --git a/internal/metastore/catalog.go b/internal/metastore/catalog.go index 301c8cc6a4..8c97f04c31 100644 --- a/internal/metastore/catalog.go +++ b/internal/metastore/catalog.go @@ -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() } diff --git a/internal/metastore/kv/kv_catalog.go b/internal/metastore/kv/kv_catalog.go index f4f343fbde..a6609a9ae8 100644 --- a/internal/metastore/kv/kv_catalog.go +++ b/internal/metastore/kv/kv_catalog.go @@ -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 } diff --git a/internal/metastore/kv/rootcorod_constant.go b/internal/metastore/kv/rootcorod_constant.go index 2222954c28..76bf1b1d14 100644 --- a/internal/metastore/kv/rootcorod_constant.go +++ b/internal/metastore/kv/rootcorod_constant.go @@ -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" ) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 0874304b89..f4aa50ec21 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -72,6 +72,7 @@ const ( queryTypeLabelName = "query_type" segmentStateLabelName = "segment_state" usernameLabelName = "username" + rolenameLabelName = "role_name" cacheNameLabelName = "cache_name" cacheStateLabelName = "cache_state" ) diff --git a/internal/metrics/rootcoord_metrics.go b/internal/metrics/rootcoord_metrics.go index 5d9aa2ce48..2f64f0aa56 100644 --- a/internal/metrics/rootcoord_metrics.go +++ b/internal/metrics/rootcoord_metrics.go @@ -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) } diff --git a/internal/proto/common.proto b/internal/proto/common.proto index e4ee2d80d0..81cb5cd24f 100644 --- a/internal/proto/common.proto +++ b/internal/proto/common.proto @@ -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 { diff --git a/internal/proto/commonpb/common.pb.go b/internal/proto/commonpb/common.pb.go index 85a647d169..c616b724eb 100644 --- a/internal/proto/commonpb/common.pb.go +++ b/internal/proto/commonpb/common.pb.go @@ -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, } diff --git a/internal/proto/internal.proto b/internal/proto/internal.proto index 40f4084463..e99b70d9bb 100644 --- a/internal/proto/internal.proto +++ b/internal/proto/internal.proto @@ -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 { diff --git a/internal/proto/internalpb/internal.pb.go b/internal/proto/internalpb/internal.pb.go index 208baf05f6..2f5aec4e1d 100644 --- a/internal/proto/internalpb/internal.pb.go +++ b/internal/proto/internalpb/internal.pb.go @@ -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, } diff --git a/internal/proto/milvus.proto b/internal/proto/milvus.proto index 80e3eba2cc..738abed97a 100644 --- a/internal/proto/milvus.proto +++ b/internal/proto/milvus.proto @@ -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; } diff --git a/internal/proto/milvuspb/milvus.pb.go b/internal/proto/milvuspb/milvus.pb.go index 9cbecaf197..3fe6942494 100644 --- a/internal/proto/milvuspb/milvus.pb.go +++ b/internal/proto/milvuspb/milvus.pb.go @@ -6447,7 +6447,7 @@ type SelectUserResponse struct { // Not useful for now Status *commonpb.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // user result array - Result []*UserResult `protobuf:"bytes,2,rep,name=result,proto3" json:"result,omitempty"` + Results []*UserResult `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6485,48 +6485,48 @@ func (m *SelectUserResponse) GetStatus() *commonpb.Status { return nil } -func (m *SelectUserResponse) GetResult() []*UserResult { +func (m *SelectUserResponse) GetResults() []*UserResult { if m != nil { - return m.Result + return m.Results } return nil } -type ResourceEntity struct { - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` +type ObjectEntity struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *ResourceEntity) Reset() { *m = ResourceEntity{} } -func (m *ResourceEntity) String() string { return proto.CompactTextString(m) } -func (*ResourceEntity) ProtoMessage() {} -func (*ResourceEntity) Descriptor() ([]byte, []int) { +func (m *ObjectEntity) Reset() { *m = ObjectEntity{} } +func (m *ObjectEntity) String() string { return proto.CompactTextString(m) } +func (*ObjectEntity) ProtoMessage() {} +func (*ObjectEntity) Descriptor() ([]byte, []int) { return fileDescriptor_02345ba45cc0e303, []int{102} } -func (m *ResourceEntity) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ResourceEntity.Unmarshal(m, b) +func (m *ObjectEntity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ObjectEntity.Unmarshal(m, b) } -func (m *ResourceEntity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ResourceEntity.Marshal(b, m, deterministic) +func (m *ObjectEntity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ObjectEntity.Marshal(b, m, deterministic) } -func (m *ResourceEntity) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResourceEntity.Merge(m, src) +func (m *ObjectEntity) XXX_Merge(src proto.Message) { + xxx_messageInfo_ObjectEntity.Merge(m, src) } -func (m *ResourceEntity) XXX_Size() int { - return xxx_messageInfo_ResourceEntity.Size(m) +func (m *ObjectEntity) XXX_Size() int { + return xxx_messageInfo_ObjectEntity.Size(m) } -func (m *ResourceEntity) XXX_DiscardUnknown() { - xxx_messageInfo_ResourceEntity.DiscardUnknown(m) +func (m *ObjectEntity) XXX_DiscardUnknown() { + xxx_messageInfo_ObjectEntity.DiscardUnknown(m) } -var xxx_messageInfo_ResourceEntity proto.InternalMessageInfo +var xxx_messageInfo_ObjectEntity proto.InternalMessageInfo -func (m *ResourceEntity) GetType() string { +func (m *ObjectEntity) GetName() string { if m != nil { - return m.Type + return m.Name } return "" } @@ -6570,251 +6570,6 @@ func (m *PrivilegeEntity) GetName() string { return "" } -type SelectResourceRequest struct { - // Not useful for now - Base *commonpb.MsgBase `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` - // resource - Entity *ResourceEntity `protobuf:"bytes,2,opt,name=entity,proto3" json:"entity,omitempty"` - // include privilege info - IncludePrivilegeInfo bool `protobuf:"varint,3,opt,name=include_privilege_info,json=includePrivilegeInfo,proto3" json:"include_privilege_info,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SelectResourceRequest) Reset() { *m = SelectResourceRequest{} } -func (m *SelectResourceRequest) String() string { return proto.CompactTextString(m) } -func (*SelectResourceRequest) ProtoMessage() {} -func (*SelectResourceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{104} -} - -func (m *SelectResourceRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SelectResourceRequest.Unmarshal(m, b) -} -func (m *SelectResourceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SelectResourceRequest.Marshal(b, m, deterministic) -} -func (m *SelectResourceRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SelectResourceRequest.Merge(m, src) -} -func (m *SelectResourceRequest) XXX_Size() int { - return xxx_messageInfo_SelectResourceRequest.Size(m) -} -func (m *SelectResourceRequest) XXX_DiscardUnknown() { - xxx_messageInfo_SelectResourceRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_SelectResourceRequest proto.InternalMessageInfo - -func (m *SelectResourceRequest) GetBase() *commonpb.MsgBase { - if m != nil { - return m.Base - } - return nil -} - -func (m *SelectResourceRequest) GetEntity() *ResourceEntity { - if m != nil { - return m.Entity - } - return nil -} - -func (m *SelectResourceRequest) GetIncludePrivilegeInfo() bool { - if m != nil { - return m.IncludePrivilegeInfo - } - return false -} - -type ResourceResult struct { - Resource *ResourceEntity `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` - Privileges []*PrivilegeEntity `protobuf:"bytes,2,rep,name=privileges,proto3" json:"privileges,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ResourceResult) Reset() { *m = ResourceResult{} } -func (m *ResourceResult) String() string { return proto.CompactTextString(m) } -func (*ResourceResult) ProtoMessage() {} -func (*ResourceResult) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{105} -} - -func (m *ResourceResult) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ResourceResult.Unmarshal(m, b) -} -func (m *ResourceResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ResourceResult.Marshal(b, m, deterministic) -} -func (m *ResourceResult) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResourceResult.Merge(m, src) -} -func (m *ResourceResult) XXX_Size() int { - return xxx_messageInfo_ResourceResult.Size(m) -} -func (m *ResourceResult) XXX_DiscardUnknown() { - xxx_messageInfo_ResourceResult.DiscardUnknown(m) -} - -var xxx_messageInfo_ResourceResult proto.InternalMessageInfo - -func (m *ResourceResult) GetResource() *ResourceEntity { - if m != nil { - return m.Resource - } - return nil -} - -func (m *ResourceResult) GetPrivileges() []*PrivilegeEntity { - if m != nil { - return m.Privileges - } - return nil -} - -type SelectResourceResponse struct { - // Not useful for now - Status *commonpb.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` - // resource result array - Results []*ResourceResult `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SelectResourceResponse) Reset() { *m = SelectResourceResponse{} } -func (m *SelectResourceResponse) String() string { return proto.CompactTextString(m) } -func (*SelectResourceResponse) ProtoMessage() {} -func (*SelectResourceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{106} -} - -func (m *SelectResourceResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SelectResourceResponse.Unmarshal(m, b) -} -func (m *SelectResourceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SelectResourceResponse.Marshal(b, m, deterministic) -} -func (m *SelectResourceResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_SelectResourceResponse.Merge(m, src) -} -func (m *SelectResourceResponse) XXX_Size() int { - return xxx_messageInfo_SelectResourceResponse.Size(m) -} -func (m *SelectResourceResponse) XXX_DiscardUnknown() { - xxx_messageInfo_SelectResourceResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_SelectResourceResponse proto.InternalMessageInfo - -func (m *SelectResourceResponse) GetStatus() *commonpb.Status { - if m != nil { - return m.Status - } - return nil -} - -func (m *SelectResourceResponse) GetResults() []*ResourceResult { - if m != nil { - return m.Results - } - return nil -} - -type PrincipalEntity struct { - // principal type, including user, role - PrincipalType string `protobuf:"bytes,1,opt,name=principal_type,json=principalType,proto3" json:"principal_type,omitempty"` - // principal, including user entity or role entity - // - // Types that are valid to be assigned to Principal: - // *PrincipalEntity_User - // *PrincipalEntity_Role - Principal isPrincipalEntity_Principal `protobuf_oneof:"principal"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PrincipalEntity) Reset() { *m = PrincipalEntity{} } -func (m *PrincipalEntity) String() string { return proto.CompactTextString(m) } -func (*PrincipalEntity) ProtoMessage() {} -func (*PrincipalEntity) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{107} -} - -func (m *PrincipalEntity) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PrincipalEntity.Unmarshal(m, b) -} -func (m *PrincipalEntity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PrincipalEntity.Marshal(b, m, deterministic) -} -func (m *PrincipalEntity) XXX_Merge(src proto.Message) { - xxx_messageInfo_PrincipalEntity.Merge(m, src) -} -func (m *PrincipalEntity) XXX_Size() int { - return xxx_messageInfo_PrincipalEntity.Size(m) -} -func (m *PrincipalEntity) XXX_DiscardUnknown() { - xxx_messageInfo_PrincipalEntity.DiscardUnknown(m) -} - -var xxx_messageInfo_PrincipalEntity proto.InternalMessageInfo - -func (m *PrincipalEntity) GetPrincipalType() string { - if m != nil { - return m.PrincipalType - } - return "" -} - -type isPrincipalEntity_Principal interface { - isPrincipalEntity_Principal() -} - -type PrincipalEntity_User struct { - User *UserEntity `protobuf:"bytes,2,opt,name=user,proto3,oneof"` -} - -type PrincipalEntity_Role struct { - Role *RoleEntity `protobuf:"bytes,3,opt,name=role,proto3,oneof"` -} - -func (*PrincipalEntity_User) isPrincipalEntity_Principal() {} - -func (*PrincipalEntity_Role) isPrincipalEntity_Principal() {} - -func (m *PrincipalEntity) GetPrincipal() isPrincipalEntity_Principal { - if m != nil { - return m.Principal - } - return nil -} - -func (m *PrincipalEntity) GetUser() *UserEntity { - if x, ok := m.GetPrincipal().(*PrincipalEntity_User); ok { - return x.User - } - return nil -} - -func (m *PrincipalEntity) GetRole() *RoleEntity { - if x, ok := m.GetPrincipal().(*PrincipalEntity_Role); ok { - return x.Role - } - return nil -} - -// XXX_OneofWrappers is for the internal use of the proto package. -func (*PrincipalEntity) XXX_OneofWrappers() []interface{} { - return []interface{}{ - (*PrincipalEntity_User)(nil), - (*PrincipalEntity_Role)(nil), - } -} - type GrantorEntity struct { User *UserEntity `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` Privilege *PrivilegeEntity `protobuf:"bytes,2,opt,name=privilege,proto3" json:"privilege,omitempty"` @@ -6827,7 +6582,7 @@ func (m *GrantorEntity) Reset() { *m = GrantorEntity{} } func (m *GrantorEntity) String() string { return proto.CompactTextString(m) } func (*GrantorEntity) ProtoMessage() {} func (*GrantorEntity) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{108} + return fileDescriptor_02345ba45cc0e303, []int{104} } func (m *GrantorEntity) XXX_Unmarshal(b []byte) error { @@ -6862,13 +6617,52 @@ func (m *GrantorEntity) GetPrivilege() *PrivilegeEntity { return nil } +type GrantPrivilegeEntity struct { + Entities []*GrantorEntity `protobuf:"bytes,1,rep,name=entities,proto3" json:"entities,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GrantPrivilegeEntity) Reset() { *m = GrantPrivilegeEntity{} } +func (m *GrantPrivilegeEntity) String() string { return proto.CompactTextString(m) } +func (*GrantPrivilegeEntity) ProtoMessage() {} +func (*GrantPrivilegeEntity) Descriptor() ([]byte, []int) { + return fileDescriptor_02345ba45cc0e303, []int{105} +} + +func (m *GrantPrivilegeEntity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GrantPrivilegeEntity.Unmarshal(m, b) +} +func (m *GrantPrivilegeEntity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GrantPrivilegeEntity.Marshal(b, m, deterministic) +} +func (m *GrantPrivilegeEntity) XXX_Merge(src proto.Message) { + xxx_messageInfo_GrantPrivilegeEntity.Merge(m, src) +} +func (m *GrantPrivilegeEntity) XXX_Size() int { + return xxx_messageInfo_GrantPrivilegeEntity.Size(m) +} +func (m *GrantPrivilegeEntity) XXX_DiscardUnknown() { + xxx_messageInfo_GrantPrivilegeEntity.DiscardUnknown(m) +} + +var xxx_messageInfo_GrantPrivilegeEntity proto.InternalMessageInfo + +func (m *GrantPrivilegeEntity) GetEntities() []*GrantorEntity { + if m != nil { + return m.Entities + } + return nil +} + type GrantEntity struct { - // principal - Principal *PrincipalEntity `protobuf:"bytes,1,opt,name=principal,proto3" json:"principal,omitempty"` - // resource - Resource *ResourceEntity `protobuf:"bytes,2,opt,name=resource,proto3" json:"resource,omitempty"` - // resource name - ResourceName string `protobuf:"bytes,3,opt,name=resource_name,json=resourceName,proto3" json:"resource_name,omitempty"` + // role + Role *RoleEntity `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` + // object + Object *ObjectEntity `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` + // object name + ObjectName string `protobuf:"bytes,3,opt,name=object_name,json=objectName,proto3" json:"object_name,omitempty"` // privilege Grantor *GrantorEntity `protobuf:"bytes,4,opt,name=grantor,proto3" json:"grantor,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -6880,7 +6674,7 @@ func (m *GrantEntity) Reset() { *m = GrantEntity{} } func (m *GrantEntity) String() string { return proto.CompactTextString(m) } func (*GrantEntity) ProtoMessage() {} func (*GrantEntity) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{109} + return fileDescriptor_02345ba45cc0e303, []int{106} } func (m *GrantEntity) XXX_Unmarshal(b []byte) error { @@ -6901,23 +6695,23 @@ func (m *GrantEntity) XXX_DiscardUnknown() { var xxx_messageInfo_GrantEntity proto.InternalMessageInfo -func (m *GrantEntity) GetPrincipal() *PrincipalEntity { +func (m *GrantEntity) GetRole() *RoleEntity { if m != nil { - return m.Principal + return m.Role } return nil } -func (m *GrantEntity) GetResource() *ResourceEntity { +func (m *GrantEntity) GetObject() *ObjectEntity { if m != nil { - return m.Resource + return m.Object } return nil } -func (m *GrantEntity) GetResourceName() string { +func (m *GrantEntity) GetObjectName() string { if m != nil { - return m.ResourceName + return m.ObjectName } return "" } @@ -6943,7 +6737,7 @@ func (m *SelectGrantRequest) Reset() { *m = SelectGrantRequest{} } func (m *SelectGrantRequest) String() string { return proto.CompactTextString(m) } func (*SelectGrantRequest) ProtoMessage() {} func (*SelectGrantRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{110} + return fileDescriptor_02345ba45cc0e303, []int{107} } func (m *SelectGrantRequest) XXX_Unmarshal(b []byte) error { @@ -6992,7 +6786,7 @@ func (m *SelectGrantResponse) Reset() { *m = SelectGrantResponse{} } func (m *SelectGrantResponse) String() string { return proto.CompactTextString(m) } func (*SelectGrantResponse) ProtoMessage() {} func (*SelectGrantResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{111} + return fileDescriptor_02345ba45cc0e303, []int{108} } func (m *SelectGrantResponse) XXX_Unmarshal(b []byte) error { @@ -7043,7 +6837,7 @@ func (m *OperatePrivilegeRequest) Reset() { *m = OperatePrivilegeRequest func (m *OperatePrivilegeRequest) String() string { return proto.CompactTextString(m) } func (*OperatePrivilegeRequest) ProtoMessage() {} func (*OperatePrivilegeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{112} + return fileDescriptor_02345ba45cc0e303, []int{109} } func (m *OperatePrivilegeRequest) XXX_Unmarshal(b []byte) error { @@ -7096,7 +6890,7 @@ func (m *MilvusExt) Reset() { *m = MilvusExt{} } func (m *MilvusExt) String() string { return proto.CompactTextString(m) } func (*MilvusExt) ProtoMessage() {} func (*MilvusExt) Descriptor() ([]byte, []int) { - return fileDescriptor_02345ba45cc0e303, []int{113} + return fileDescriptor_02345ba45cc0e303, []int{110} } func (m *MilvusExt) XXX_Unmarshal(b []byte) error { @@ -7240,13 +7034,10 @@ func init() { proto.RegisterType((*SelectUserRequest)(nil), "milvus.proto.milvus.SelectUserRequest") proto.RegisterType((*UserResult)(nil), "milvus.proto.milvus.UserResult") proto.RegisterType((*SelectUserResponse)(nil), "milvus.proto.milvus.SelectUserResponse") - proto.RegisterType((*ResourceEntity)(nil), "milvus.proto.milvus.ResourceEntity") + proto.RegisterType((*ObjectEntity)(nil), "milvus.proto.milvus.ObjectEntity") proto.RegisterType((*PrivilegeEntity)(nil), "milvus.proto.milvus.PrivilegeEntity") - proto.RegisterType((*SelectResourceRequest)(nil), "milvus.proto.milvus.SelectResourceRequest") - proto.RegisterType((*ResourceResult)(nil), "milvus.proto.milvus.ResourceResult") - proto.RegisterType((*SelectResourceResponse)(nil), "milvus.proto.milvus.SelectResourceResponse") - proto.RegisterType((*PrincipalEntity)(nil), "milvus.proto.milvus.PrincipalEntity") proto.RegisterType((*GrantorEntity)(nil), "milvus.proto.milvus.GrantorEntity") + proto.RegisterType((*GrantPrivilegeEntity)(nil), "milvus.proto.milvus.GrantPrivilegeEntity") proto.RegisterType((*GrantEntity)(nil), "milvus.proto.milvus.GrantEntity") proto.RegisterType((*SelectGrantRequest)(nil), "milvus.proto.milvus.SelectGrantRequest") proto.RegisterType((*SelectGrantResponse)(nil), "milvus.proto.milvus.SelectGrantResponse") @@ -7258,334 +7049,326 @@ func init() { func init() { proto.RegisterFile("milvus.proto", fileDescriptor_02345ba45cc0e303) } var fileDescriptor_02345ba45cc0e303 = []byte{ - // 5226 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x7d, 0xdd, 0x6f, 0x1c, 0x47, - 0x72, 0x38, 0x67, 0x97, 0xfb, 0x55, 0xfb, 0xc1, 0x65, 0xf3, 0x6b, 0xbd, 0x92, 0x2c, 0x6a, 0x6c, - 0xd9, 0xb4, 0x74, 0xa6, 0x6c, 0xca, 0x1f, 0x77, 0xb2, 0xcf, 0xb6, 0x28, 0x5a, 0x12, 0x61, 0x7d, - 0xd0, 0x43, 0xf9, 0x7e, 0xb8, 0x9f, 0x21, 0x4c, 0x86, 0x3b, 0xcd, 0xe5, 0x58, 0xb3, 0x33, 0xab, - 0x99, 0x59, 0x52, 0xf4, 0x43, 0x60, 0xe4, 0x2e, 0x5f, 0x88, 0x73, 0x87, 0x43, 0x0e, 0x31, 0xee, - 0x21, 0x41, 0x2e, 0x5f, 0x6f, 0x09, 0x72, 0x77, 0x0f, 0x01, 0x92, 0x00, 0x49, 0x80, 0x7b, 0x08, - 0x8c, 0x20, 0xb9, 0x3c, 0x05, 0x81, 0xff, 0x80, 0x20, 0x0f, 0x01, 0x12, 0x20, 0x79, 0x4b, 0x80, - 0xa0, 0x3f, 0x66, 0xb6, 0x67, 0xb6, 0x67, 0xb9, 0xe4, 0x9e, 0x4c, 0xea, 0x6d, 0xa7, 0xba, 0xba, - 0xbb, 0xba, 0xba, 0xaa, 0xba, 0xba, 0xab, 0xba, 0x17, 0x2a, 0x1d, 0xcb, 0xde, 0xed, 0xf9, 0xcb, - 0x5d, 0xcf, 0x0d, 0x5c, 0x34, 0x23, 0x7e, 0x2d, 0xb3, 0x8f, 0x66, 0xa5, 0xe5, 0x76, 0x3a, 0xae, - 0xc3, 0x80, 0xcd, 0x8a, 0xdf, 0xda, 0xc1, 0x1d, 0x83, 0x7f, 0x2d, 0xb6, 0x5d, 0xb7, 0x6d, 0xe3, - 0x4b, 0xf4, 0x6b, 0xab, 0xb7, 0x7d, 0xc9, 0xc4, 0x7e, 0xcb, 0xb3, 0xba, 0x81, 0xeb, 0x31, 0x0c, - 0xf5, 0x77, 0x15, 0x40, 0xd7, 0x3c, 0x6c, 0x04, 0xf8, 0xaa, 0x6d, 0x19, 0xbe, 0x86, 0x1f, 0xf6, - 0xb0, 0x1f, 0xa0, 0x97, 0x60, 0x72, 0xcb, 0xf0, 0x71, 0x43, 0x59, 0x54, 0x96, 0xca, 0x2b, 0xa7, - 0x97, 0x63, 0x1d, 0xf3, 0x0e, 0x6f, 0xfb, 0xed, 0x55, 0xc3, 0xc7, 0x1a, 0xc5, 0x44, 0x0b, 0x50, - 0x30, 0xb7, 0x74, 0xc7, 0xe8, 0xe0, 0x46, 0x66, 0x51, 0x59, 0x2a, 0x69, 0x79, 0x73, 0xeb, 0x8e, - 0xd1, 0xc1, 0xe8, 0x79, 0x98, 0x6a, 0xb9, 0xb6, 0x8d, 0x5b, 0x81, 0xe5, 0x3a, 0x0c, 0x21, 0x4b, - 0x11, 0x6a, 0x7d, 0x30, 0x45, 0x9c, 0x85, 0x9c, 0x41, 0x68, 0x68, 0x4c, 0xd2, 0x62, 0xf6, 0xa1, - 0xfa, 0x50, 0x5f, 0xf3, 0xdc, 0xee, 0xe3, 0xa2, 0x2e, 0xea, 0x34, 0x2b, 0x76, 0xfa, 0x3b, 0x0a, - 0x4c, 0x5f, 0xb5, 0x03, 0xec, 0x9d, 0x50, 0xa6, 0xfc, 0x30, 0x03, 0x0b, 0x6c, 0xd6, 0xae, 0x45, - 0xe8, 0xc7, 0x49, 0xe5, 0x3c, 0xe4, 0x99, 0xdc, 0x51, 0x32, 0x2b, 0x1a, 0xff, 0x42, 0x67, 0x00, - 0xfc, 0x1d, 0xc3, 0x33, 0x7d, 0xdd, 0xe9, 0x75, 0x1a, 0xb9, 0x45, 0x65, 0x29, 0xa7, 0x95, 0x18, - 0xe4, 0x4e, 0xaf, 0x83, 0x34, 0x98, 0x6e, 0xb9, 0x8e, 0x6f, 0xf9, 0x01, 0x76, 0x5a, 0xfb, 0xba, - 0x8d, 0x77, 0xb1, 0xdd, 0xc8, 0x2f, 0x2a, 0x4b, 0xb5, 0x95, 0xf3, 0x52, 0xba, 0xaf, 0xf5, 0xb1, - 0x6f, 0x11, 0x64, 0xad, 0xde, 0x4a, 0x40, 0xae, 0x14, 0x3e, 0x7f, 0x6b, 0xb2, 0xae, 0x34, 0xb2, - 0xea, 0xf7, 0x15, 0x98, 0x23, 0x92, 0x73, 0x22, 0x38, 0xc4, 0xc8, 0xca, 0x34, 0xb2, 0xea, 0x8f, - 0x15, 0x98, 0xbd, 0x69, 0xf8, 0x27, 0x63, 0xde, 0xce, 0x00, 0x04, 0x56, 0x07, 0xeb, 0x7e, 0x60, - 0x74, 0xba, 0x74, 0xee, 0x26, 0xb5, 0x12, 0x81, 0x6c, 0x12, 0x00, 0x23, 0x7a, 0xb2, 0x91, 0x55, - 0xbf, 0x09, 0x95, 0x55, 0xd7, 0xb5, 0x35, 0xec, 0x77, 0x5d, 0xc7, 0xc7, 0xe8, 0x32, 0xe4, 0xfd, - 0xc0, 0x08, 0x7a, 0x3e, 0xa7, 0xf6, 0x94, 0x94, 0xda, 0x4d, 0x8a, 0xa2, 0x71, 0x54, 0x22, 0xca, - 0xbb, 0x86, 0xdd, 0x63, 0xc4, 0x16, 0x35, 0xf6, 0xa1, 0x7e, 0x08, 0xb5, 0xcd, 0xc0, 0xb3, 0x9c, - 0xf6, 0xcf, 0xb1, 0xf1, 0x52, 0xd8, 0xf8, 0x17, 0x0a, 0x3c, 0xb5, 0x46, 0x4d, 0xde, 0xd6, 0x09, - 0xd1, 0x14, 0x15, 0x2a, 0x7d, 0xc8, 0xfa, 0x1a, 0xe5, 0x79, 0x56, 0x8b, 0xc1, 0x12, 0xb3, 0x92, - 0x4b, 0x9d, 0x95, 0x4f, 0x72, 0xd0, 0x94, 0x8d, 0x6e, 0x1c, 0x3e, 0x7e, 0x3d, 0xd2, 0xe4, 0x0c, - 0xad, 0x94, 0xd0, 0x43, 0xbe, 0xba, 0xf4, 0x7b, 0xdb, 0xa4, 0x80, 0x48, 0xe1, 0x93, 0xc3, 0xcb, - 0x4a, 0x86, 0xb7, 0x02, 0x73, 0xbb, 0x96, 0x17, 0xf4, 0x0c, 0x5b, 0x6f, 0xed, 0x18, 0x8e, 0x83, - 0x6d, 0xca, 0x30, 0x62, 0xe2, 0xb2, 0x4b, 0x25, 0x6d, 0x86, 0x17, 0x5e, 0x63, 0x65, 0x84, 0x6b, - 0x3e, 0x7a, 0x05, 0xe6, 0xbb, 0x3b, 0xfb, 0xbe, 0xd5, 0x1a, 0xa8, 0x94, 0xa3, 0x95, 0x66, 0xc3, - 0xd2, 0x58, 0xad, 0x8b, 0x30, 0xdd, 0xa2, 0x56, 0xd2, 0xd4, 0x09, 0xfb, 0x18, 0x3f, 0xf3, 0x94, - 0x9f, 0x75, 0x5e, 0x70, 0x2f, 0x84, 0x13, 0xb2, 0x42, 0xe4, 0x5e, 0xd0, 0x12, 0x2a, 0x14, 0x68, - 0x85, 0x19, 0x5e, 0xf8, 0x41, 0xd0, 0xea, 0xd7, 0x89, 0xdb, 0xb7, 0x62, 0xd2, 0xbe, 0x35, 0xa0, - 0x40, 0xed, 0x35, 0xf6, 0x1b, 0x25, 0x4a, 0x66, 0xf8, 0x89, 0xd6, 0x61, 0xca, 0x0f, 0x0c, 0x2f, - 0xd0, 0xbb, 0xae, 0x6f, 0x11, 0xbe, 0xf8, 0x0d, 0x58, 0xcc, 0x2e, 0x95, 0x57, 0x16, 0xa5, 0x93, - 0xf4, 0x1e, 0xde, 0x5f, 0x33, 0x02, 0x63, 0xc3, 0xb0, 0x3c, 0xad, 0x46, 0x2b, 0x6e, 0x84, 0xf5, - 0xe4, 0x46, 0xb4, 0x3c, 0x96, 0x11, 0x95, 0x89, 0x73, 0x45, 0x26, 0xce, 0xea, 0x5f, 0x2a, 0x30, - 0x77, 0xcb, 0x35, 0xcc, 0x93, 0xa1, 0x5c, 0xe7, 0xa1, 0xe6, 0xe1, 0xae, 0x6d, 0xb5, 0x0c, 0x32, - 0x1f, 0x5b, 0xd8, 0xa3, 0xea, 0x95, 0xd3, 0xaa, 0x1c, 0x7a, 0x87, 0x02, 0x99, 0x02, 0xe5, 0x1a, - 0x59, 0xf5, 0x33, 0x05, 0x1a, 0x1a, 0xb6, 0xb1, 0xe1, 0xe3, 0x13, 0xb4, 0x4a, 0xe4, 0x1b, 0x59, - 0xf5, 0xdf, 0x15, 0x98, 0xbd, 0x81, 0x03, 0xa2, 0x9c, 0x96, 0x1f, 0x58, 0xad, 0x63, 0xf5, 0x41, - 0x9e, 0x87, 0xa9, 0xae, 0xe1, 0x05, 0x56, 0x84, 0x17, 0xaa, 0x6a, 0x2d, 0x02, 0x33, 0x7d, 0xbb, - 0x04, 0x33, 0xed, 0x9e, 0xe1, 0x19, 0x4e, 0x80, 0xb1, 0xa0, 0x40, 0xcc, 0x82, 0xa1, 0xa8, 0x28, - 0xd2, 0x9f, 0xbe, 0x29, 0xfb, 0x65, 0x05, 0xe6, 0x12, 0xe3, 0x1d, 0xc7, 0x8a, 0xbd, 0x0e, 0x39, - 0xf2, 0xcb, 0x6f, 0x64, 0xa8, 0x52, 0x9d, 0x4b, 0x53, 0xaa, 0x6f, 0x90, 0x55, 0x82, 0x6a, 0x15, - 0xc3, 0x27, 0x8e, 0xdf, 0xd3, 0x37, 0x70, 0x20, 0xd8, 0xb7, 0x93, 0x30, 0x03, 0x7d, 0x3e, 0x7d, - 0x57, 0x81, 0xb3, 0xa9, 0xf4, 0x1d, 0x0b, 0xc7, 0xfe, 0x55, 0x81, 0xf9, 0xcd, 0x1d, 0x77, 0xaf, - 0x4f, 0xd2, 0xe3, 0xe0, 0x54, 0x7c, 0x49, 0xcc, 0x26, 0x96, 0x44, 0xf4, 0x32, 0x4c, 0x06, 0xfb, - 0x5d, 0x4c, 0xd5, 0xbd, 0xb6, 0x72, 0x66, 0x59, 0xb2, 0x4f, 0x5a, 0x26, 0x44, 0xde, 0xdb, 0xef, - 0x62, 0x8d, 0xa2, 0xa2, 0x17, 0xa0, 0x9e, 0xe0, 0x7d, 0xb8, 0x96, 0x4c, 0xc5, 0x99, 0xef, 0x5f, - 0xc9, 0x7d, 0xfe, 0x56, 0xa6, 0x3e, 0xa9, 0xfe, 0x47, 0x06, 0x16, 0x06, 0x46, 0x3a, 0x0e, 0xcf, - 0x65, 0x24, 0x64, 0xa4, 0x24, 0x10, 0xcb, 0x26, 0xa0, 0x5a, 0x26, 0xd9, 0xaf, 0x64, 0x97, 0xb2, - 0x5a, 0x55, 0x58, 0x59, 0x4d, 0x1f, 0xbd, 0x08, 0x68, 0x60, 0xc1, 0x63, 0xca, 0x3a, 0xa9, 0x4d, - 0x27, 0x57, 0x3c, 0xba, 0xaa, 0x4a, 0x97, 0x3c, 0xc6, 0x89, 0x49, 0x6d, 0x56, 0xb2, 0xe6, 0xf9, - 0xe8, 0x65, 0x98, 0xb5, 0x9c, 0xdb, 0xb8, 0xe3, 0x7a, 0xfb, 0x7a, 0x17, 0x7b, 0x2d, 0xec, 0x04, - 0x46, 0x1b, 0xfb, 0x8d, 0x3c, 0xa5, 0x68, 0x26, 0x2c, 0xdb, 0xe8, 0x17, 0xa1, 0xd7, 0x60, 0xe1, - 0x61, 0x0f, 0x7b, 0xfb, 0xba, 0x8f, 0xbd, 0x5d, 0xab, 0x85, 0x75, 0x63, 0xd7, 0xb0, 0x6c, 0x63, - 0xcb, 0xc6, 0x8d, 0xc2, 0x62, 0x76, 0xa9, 0xa8, 0xcd, 0xd1, 0xe2, 0x4d, 0x56, 0x7a, 0x35, 0x2c, - 0x54, 0x7f, 0xa2, 0xc0, 0x3c, 0xdb, 0xe7, 0x6c, 0x84, 0x96, 0xe6, 0x98, 0xd7, 0x97, 0xb8, 0x21, - 0xe4, 0xbb, 0xb2, 0x6a, 0xcc, 0x0e, 0xaa, 0x3f, 0x52, 0x60, 0x96, 0xec, 0x3c, 0x9e, 0x24, 0x9a, - 0xff, 0x4c, 0x81, 0x99, 0x9b, 0x86, 0xff, 0x24, 0x91, 0xfc, 0x05, 0xf7, 0x3d, 0x22, 0x9a, 0x9f, - 0x8c, 0x45, 0x72, 0xd0, 0x49, 0xc9, 0x49, 0x9c, 0x14, 0xf5, 0xcf, 0xfb, 0xbe, 0xc9, 0x93, 0x35, - 0x40, 0xf5, 0x2f, 0x14, 0x38, 0x73, 0x03, 0x07, 0x11, 0xd5, 0x27, 0xc3, 0x89, 0x19, 0x51, 0xa8, - 0xbe, 0xc3, 0x1c, 0x00, 0x29, 0xf1, 0xc7, 0xb2, 0xbe, 0xfe, 0x46, 0x06, 0xe6, 0xc8, 0xaa, 0x73, - 0x32, 0x84, 0x60, 0x94, 0xed, 0xab, 0x44, 0x50, 0x72, 0x52, 0x4d, 0x08, 0x57, 0xed, 0xfc, 0xc8, - 0xab, 0xb6, 0xfa, 0xe3, 0x0c, 0xf3, 0x36, 0x44, 0x6e, 0x8c, 0x33, 0x2d, 0x12, 0x5a, 0x33, 0x52, - 0x5a, 0x55, 0xa8, 0x44, 0x90, 0xf5, 0xb5, 0x70, 0xf9, 0x8d, 0xc1, 0x4e, 0xea, 0xea, 0xab, 0x7e, - 0xaa, 0xc0, 0x7c, 0x78, 0x4e, 0xb0, 0x89, 0xdb, 0x1d, 0xec, 0x04, 0x47, 0x97, 0xa1, 0xa4, 0x04, - 0x64, 0x24, 0x12, 0x70, 0x1a, 0x4a, 0x3e, 0xeb, 0x27, 0x3a, 0x02, 0xe8, 0x03, 0xd4, 0xbf, 0x56, - 0x60, 0x61, 0x80, 0x9c, 0x71, 0x26, 0xb1, 0x01, 0x05, 0xcb, 0x31, 0xf1, 0xa3, 0x88, 0x9a, 0xf0, - 0x93, 0x94, 0x6c, 0xf5, 0x2c, 0xdb, 0x8c, 0xc8, 0x08, 0x3f, 0xd1, 0x39, 0xa8, 0x60, 0x87, 0xf8, - 0x18, 0x3a, 0xc5, 0xa5, 0x82, 0x5c, 0xd4, 0xca, 0x0c, 0xb6, 0x4e, 0x40, 0xa4, 0xf2, 0xb6, 0x85, - 0x69, 0xe5, 0x1c, 0xab, 0xcc, 0x3f, 0xd5, 0xdf, 0x54, 0x60, 0x86, 0x48, 0x21, 0xa7, 0xde, 0x7f, - 0xbc, 0xdc, 0x5c, 0x84, 0xb2, 0x20, 0x66, 0x7c, 0x20, 0x22, 0x48, 0x7d, 0x00, 0xb3, 0x71, 0x72, - 0xc6, 0xe1, 0xe6, 0xd3, 0x00, 0xd1, 0x5c, 0x31, 0x6d, 0xc8, 0x6a, 0x02, 0x44, 0xfd, 0x34, 0x13, - 0x46, 0x0c, 0x28, 0x9b, 0x8e, 0xf9, 0xf8, 0x92, 0x4e, 0x89, 0x68, 0xcf, 0x4b, 0x14, 0x42, 0x8b, - 0xd7, 0xa0, 0x82, 0x1f, 0x05, 0x9e, 0xa1, 0x77, 0x0d, 0xcf, 0xe8, 0x30, 0xb5, 0x1a, 0xc9, 0xf4, - 0x96, 0x69, 0xb5, 0x0d, 0x5a, 0x8b, 0x74, 0x42, 0x45, 0x84, 0x75, 0x92, 0x67, 0x9d, 0x50, 0x08, - 0x5d, 0x30, 0xfe, 0x8e, 0x38, 0x7b, 0x5c, 0x9a, 0x4f, 0x3a, 0x43, 0xe2, 0x43, 0xc9, 0x25, 0x87, - 0xf2, 0x47, 0x0a, 0xd4, 0xe9, 0x10, 0xd6, 0x78, 0x94, 0xc8, 0x72, 0x9d, 0x44, 0x1d, 0x25, 0x51, - 0x67, 0x88, 0xee, 0x7d, 0x0d, 0xf2, 0x9c, 0xef, 0xd9, 0x51, 0xf9, 0xce, 0x2b, 0x1c, 0x30, 0x0c, - 0xf5, 0xf7, 0x15, 0x98, 0x4b, 0xb0, 0x7c, 0x1c, 0x81, 0xbf, 0x07, 0x88, 0x8d, 0xd0, 0xec, 0x0f, - 0x3b, 0x5c, 0xa7, 0xcf, 0x4b, 0x17, 0xa5, 0x24, 0x93, 0xb4, 0x69, 0x2b, 0x01, 0xf1, 0xd5, 0x9f, - 0x29, 0x70, 0xfa, 0x06, 0x0e, 0x28, 0xea, 0x2a, 0x31, 0x3a, 0x1b, 0x9e, 0xdb, 0xf6, 0xb0, 0xef, - 0x3f, 0xb9, 0xf2, 0xf1, 0xdb, 0xcc, 0xb1, 0x93, 0x0d, 0x69, 0x1c, 0xfe, 0x9f, 0x83, 0x0a, 0xed, - 0x03, 0x9b, 0xba, 0xe7, 0xee, 0xf9, 0x5c, 0x8e, 0xca, 0x1c, 0xa6, 0xb9, 0x7b, 0x54, 0x20, 0x02, - 0x37, 0x30, 0x6c, 0x86, 0xc0, 0x57, 0x14, 0x0a, 0x21, 0xc5, 0x54, 0x07, 0x43, 0xc2, 0x48, 0xe3, - 0xf8, 0xc9, 0xe5, 0xf1, 0x1f, 0xb2, 0x83, 0x30, 0x71, 0x28, 0xe3, 0xf0, 0xf6, 0x55, 0xe6, 0x76, - 0xb2, 0xc1, 0xd4, 0x56, 0xce, 0x4a, 0xeb, 0x08, 0x9d, 0x31, 0x6c, 0x74, 0x16, 0xca, 0xdb, 0x86, - 0x65, 0xeb, 0x1e, 0x36, 0x7c, 0xd7, 0xe1, 0x03, 0x05, 0x02, 0xd2, 0x28, 0x44, 0xfd, 0xa9, 0xc2, - 0xc2, 0xb2, 0x4f, 0xb8, 0xc5, 0xfb, 0x83, 0x0c, 0x54, 0xd7, 0x1d, 0x1f, 0x7b, 0xc1, 0xc9, 0xdf, - 0x9a, 0xa0, 0xb7, 0xa1, 0x4c, 0x07, 0xe6, 0xeb, 0xa6, 0x11, 0x18, 0x7c, 0x35, 0x7b, 0x5a, 0x1a, - 0x9f, 0xb9, 0x4e, 0xf0, 0xd6, 0x8c, 0xc0, 0xd0, 0x18, 0x77, 0x7c, 0xf2, 0x1b, 0x9d, 0x82, 0xd2, - 0x8e, 0xe1, 0xef, 0xe8, 0x0f, 0xf0, 0x3e, 0xf3, 0x17, 0xab, 0x5a, 0x91, 0x00, 0xde, 0xc3, 0xfb, - 0x3e, 0x7a, 0x0a, 0x8a, 0x4e, 0xaf, 0xc3, 0x14, 0xac, 0xb0, 0xa8, 0x2c, 0x55, 0xb5, 0x82, 0xd3, - 0xeb, 0x50, 0xf5, 0xfa, 0xfb, 0x0c, 0xd4, 0x6e, 0xf7, 0xc8, 0x46, 0x88, 0x46, 0x97, 0x7a, 0x76, - 0x70, 0x34, 0x61, 0xbc, 0x00, 0x59, 0xe6, 0x52, 0x90, 0x1a, 0x0d, 0x29, 0xe1, 0xeb, 0x6b, 0xbe, - 0x46, 0x90, 0x68, 0x64, 0xa5, 0xd7, 0x6a, 0x71, 0xef, 0x2c, 0x4b, 0x89, 0x2d, 0x11, 0x08, 0xf3, - 0xcd, 0x4e, 0x41, 0x09, 0x7b, 0x5e, 0xe4, 0xbb, 0xd1, 0xa1, 0x60, 0xcf, 0x63, 0x85, 0x2a, 0x54, - 0x8c, 0xd6, 0x03, 0xc7, 0xdd, 0xb3, 0xb1, 0xd9, 0xc6, 0x26, 0x9d, 0xf6, 0xa2, 0x16, 0x83, 0x31, - 0xc1, 0x20, 0x13, 0xaf, 0xb7, 0x9c, 0x80, 0xae, 0xea, 0x59, 0x22, 0x18, 0x04, 0x72, 0xcd, 0x09, - 0x48, 0xb1, 0x89, 0x6d, 0x1c, 0x60, 0x5a, 0x5c, 0x60, 0xc5, 0x0c, 0xc2, 0x8b, 0x7b, 0xdd, 0xa8, - 0x76, 0x91, 0x15, 0x33, 0x08, 0x29, 0x3e, 0x0d, 0xa5, 0xfe, 0xe9, 0x77, 0xa9, 0x7f, 0x58, 0x49, - 0x01, 0xea, 0x17, 0x0a, 0x54, 0xd7, 0x68, 0x53, 0x4f, 0x80, 0xd0, 0x21, 0x98, 0xc4, 0x8f, 0xba, - 0x1e, 0x57, 0x1d, 0xfa, 0x7b, 0xa8, 0x1c, 0xa9, 0xff, 0x9b, 0x85, 0xea, 0x26, 0x36, 0xbc, 0xd6, - 0xce, 0x13, 0x71, 0x1a, 0x53, 0x87, 0xac, 0xe9, 0xdb, 0x7c, 0x78, 0xe4, 0x27, 0xba, 0x08, 0xd3, - 0x5d, 0xdb, 0x68, 0xe1, 0x1d, 0xd7, 0x36, 0xb1, 0xa7, 0xb7, 0x3d, 0xb7, 0xc7, 0x82, 0x86, 0x15, - 0xad, 0x2e, 0x14, 0xdc, 0x20, 0x70, 0xf4, 0x3a, 0x14, 0x4d, 0xdf, 0xd6, 0xe9, 0x36, 0xb6, 0x40, - 0x4d, 0xac, 0x7c, 0x7c, 0x6b, 0xbe, 0x4d, 0x77, 0xb1, 0x05, 0x93, 0xfd, 0x40, 0xcf, 0x40, 0xd5, - 0xed, 0x05, 0xdd, 0x5e, 0xa0, 0x33, 0x05, 0x6d, 0x14, 0x29, 0x79, 0x15, 0x06, 0xa4, 0xfa, 0xeb, - 0xa3, 0xeb, 0x50, 0xf5, 0x29, 0x2b, 0x43, 0x0f, 0xb6, 0x34, 0xaa, 0x27, 0x55, 0x61, 0xf5, 0xb8, - 0x0b, 0xfb, 0x02, 0xd4, 0x03, 0xcf, 0xd8, 0xc5, 0xb6, 0x10, 0x94, 0x01, 0x2a, 0x96, 0x53, 0x0c, - 0xde, 0x8f, 0x68, 0xa6, 0x84, 0x70, 0xca, 0x69, 0x21, 0x1c, 0x54, 0x83, 0x8c, 0xf3, 0x90, 0x46, - 0x07, 0xb3, 0x5a, 0xc6, 0x79, 0xa8, 0xbe, 0x07, 0x93, 0x37, 0xad, 0x80, 0x32, 0x96, 0x28, 0xbb, - 0x42, 0xf7, 0x0f, 0x54, 0xa5, 0x9f, 0x82, 0xa2, 0xe7, 0xee, 0x31, 0xe3, 0x45, 0xbc, 0xab, 0x8a, - 0x56, 0xf0, 0xdc, 0x3d, 0x6a, 0x99, 0x68, 0xfe, 0x88, 0xeb, 0x61, 0xe6, 0x2b, 0x66, 0x34, 0xfe, - 0xa5, 0xfe, 0xa9, 0xd2, 0x17, 0x26, 0x62, 0x77, 0xfc, 0xa3, 0x19, 0x9e, 0xb7, 0xa1, 0xe0, 0xb1, - 0xfa, 0x43, 0xa3, 0xda, 0x62, 0x4f, 0xd4, 0x78, 0x86, 0xb5, 0x46, 0x96, 0x3b, 0xf5, 0xdb, 0x0a, - 0x54, 0xae, 0xdb, 0x3d, 0xff, 0x71, 0x08, 0xbf, 0x2c, 0x5c, 0x90, 0x95, 0x86, 0x0b, 0xd4, 0xef, - 0x65, 0xa0, 0xca, 0xc9, 0x18, 0xc7, 0x7b, 0x48, 0x25, 0x65, 0x13, 0xca, 0xa4, 0x4b, 0xdd, 0xc7, - 0xed, 0xf0, 0x30, 0xa4, 0xbc, 0xb2, 0x22, 0xf5, 0x95, 0x63, 0x64, 0xd0, 0xc4, 0x81, 0x4d, 0x5a, - 0xe9, 0x5d, 0x27, 0xf0, 0xf6, 0x35, 0x68, 0x45, 0x80, 0xe6, 0x7d, 0x98, 0x4a, 0x14, 0x13, 0x21, - 0x7a, 0x80, 0xf7, 0xf9, 0xae, 0x83, 0xfc, 0x44, 0xaf, 0x88, 0x79, 0x1e, 0x69, 0xcb, 0xdf, 0x2d, - 0xd7, 0x69, 0x5f, 0xf5, 0x3c, 0x63, 0x9f, 0xe7, 0x81, 0x5c, 0xc9, 0x7c, 0x55, 0x51, 0xff, 0x26, - 0x03, 0x95, 0xf7, 0x7b, 0xd8, 0xdb, 0x3f, 0x4e, 0xbb, 0x14, 0x9a, 0xd3, 0x49, 0xc1, 0x9c, 0x0e, - 0x98, 0x82, 0x9c, 0xc4, 0x14, 0x48, 0x0c, 0x5a, 0x5e, 0x6a, 0xd0, 0x64, 0xba, 0x5e, 0x38, 0x94, - 0xae, 0x17, 0xd3, 0x74, 0x5d, 0xfd, 0x13, 0x25, 0x62, 0xe1, 0x58, 0xda, 0x18, 0xf3, 0x63, 0x32, - 0x87, 0xf6, 0x63, 0x46, 0xd6, 0xc6, 0x1f, 0x29, 0x50, 0xfa, 0x06, 0x6e, 0x05, 0xae, 0x47, 0xec, - 0x8f, 0xa4, 0x9a, 0x32, 0x82, 0x4f, 0x99, 0x49, 0xfa, 0x94, 0x97, 0xa1, 0x68, 0x99, 0xba, 0x41, - 0xe4, 0x8b, 0xf6, 0x3b, 0xcc, 0x97, 0x29, 0x58, 0x26, 0x15, 0xc4, 0xd1, 0x4f, 0xcf, 0x3f, 0x53, - 0xa0, 0xc2, 0x68, 0xf6, 0x59, 0xcd, 0x37, 0x84, 0xee, 0x14, 0x99, 0xd0, 0xf3, 0x8f, 0x68, 0xa0, - 0x37, 0x27, 0xfa, 0xdd, 0x5e, 0x05, 0x20, 0x4c, 0xe6, 0xd5, 0x99, 0xce, 0x2c, 0x4a, 0xa9, 0x65, - 0xd5, 0x29, 0xc3, 0x6f, 0x4e, 0x68, 0x25, 0x52, 0x8b, 0x36, 0xb1, 0x5a, 0x80, 0x1c, 0xad, 0xad, - 0xfe, 0x8f, 0x02, 0x33, 0xd7, 0x0c, 0xbb, 0xb5, 0x66, 0xf9, 0x81, 0xe1, 0xb4, 0xc6, 0xf0, 0x5e, - 0xae, 0x40, 0xc1, 0xed, 0xea, 0x36, 0xde, 0x0e, 0x38, 0x49, 0xe7, 0x86, 0x8c, 0x88, 0xb1, 0x41, - 0xcb, 0xbb, 0xdd, 0x5b, 0x78, 0x3b, 0x40, 0x6f, 0x42, 0xd1, 0xed, 0xea, 0x9e, 0xd5, 0xde, 0x09, - 0x38, 0xf7, 0x47, 0xa8, 0x5c, 0x70, 0xbb, 0x1a, 0xa9, 0x21, 0x1c, 0x4a, 0x4c, 0x1e, 0xf2, 0x50, - 0x42, 0xfd, 0xa7, 0x81, 0xe1, 0x8f, 0xa1, 0x03, 0x57, 0xa0, 0x68, 0x39, 0x81, 0x6e, 0x5a, 0x7e, - 0xc8, 0x82, 0x33, 0x72, 0x19, 0x72, 0x02, 0x3a, 0x02, 0x3a, 0xa7, 0x4e, 0x40, 0xfa, 0x46, 0xef, - 0x00, 0x6c, 0xdb, 0xae, 0xc1, 0x6b, 0x33, 0x1e, 0x9c, 0x95, 0xab, 0x0f, 0x41, 0x0b, 0xeb, 0x97, - 0x68, 0x25, 0xd2, 0x42, 0x7f, 0x4a, 0xff, 0x51, 0x81, 0xb9, 0x0d, 0xec, 0xb1, 0xe4, 0x9f, 0x80, - 0x9f, 0x1f, 0xae, 0x3b, 0xdb, 0x6e, 0xfc, 0x08, 0x57, 0x49, 0x1c, 0xe1, 0xfe, 0x7c, 0x8e, 0x2d, - 0x63, 0x5b, 0x0e, 0x16, 0x48, 0x08, 0xb7, 0x1c, 0x61, 0xb8, 0x84, 0x6d, 0xd9, 0x6a, 0x29, 0xd3, - 0xc4, 0xe9, 0x15, 0x77, 0xae, 0xea, 0x6f, 0xb1, 0x04, 0x09, 0xe9, 0xa0, 0x8e, 0x2e, 0xb0, 0xf3, - 0xc0, 0x2d, 0x7d, 0xc2, 0xee, 0x3f, 0x07, 0x09, 0xdb, 0x91, 0x62, 0x88, 0x7e, 0xa0, 0xc0, 0x62, - 0x3a, 0x55, 0xe3, 0x2c, 0xd1, 0xef, 0x40, 0xce, 0x72, 0xb6, 0xdd, 0xf0, 0xbc, 0xea, 0x82, 0x54, - 0x17, 0xe4, 0xfd, 0xb2, 0x8a, 0xea, 0xcf, 0x32, 0x50, 0x7f, 0x9f, 0x45, 0xdf, 0xbf, 0xf4, 0xe9, - 0xef, 0xe0, 0x8e, 0xee, 0x5b, 0x1f, 0xe3, 0x70, 0xfa, 0x3b, 0xb8, 0xb3, 0x69, 0x7d, 0x8c, 0x63, - 0x92, 0x91, 0x8b, 0x4b, 0xc6, 0xf0, 0xe3, 0x58, 0xf1, 0x3c, 0xb2, 0x10, 0x3f, 0x8f, 0x9c, 0x87, - 0xbc, 0xe3, 0x9a, 0x78, 0x7d, 0x8d, 0xef, 0xd7, 0xf8, 0x57, 0x5f, 0xd4, 0x4a, 0x87, 0x13, 0x35, - 0xd2, 0x15, 0x6d, 0xc2, 0x64, 0xb9, 0x7b, 0x84, 0x46, 0xf6, 0xa9, 0x7e, 0x47, 0x81, 0xe6, 0x0d, - 0x1c, 0x24, 0xb9, 0x7a, 0x7c, 0xf2, 0xf7, 0x5d, 0x05, 0x4e, 0x49, 0x09, 0x1a, 0x47, 0xf4, 0xde, - 0x88, 0x8b, 0x9e, 0xfc, 0xa8, 0x74, 0xa0, 0x4b, 0x2e, 0x75, 0x2f, 0x43, 0x65, 0xad, 0xd7, 0xe9, - 0x44, 0xce, 0xd8, 0x39, 0xa8, 0x78, 0xec, 0x27, 0xdb, 0x4c, 0xb1, 0x95, 0xb9, 0xcc, 0x61, 0x64, - 0xcb, 0xa4, 0x5e, 0x84, 0x2a, 0xaf, 0xc2, 0xa9, 0x6e, 0x42, 0xd1, 0xe3, 0xbf, 0x39, 0x7e, 0xf4, - 0xad, 0xce, 0xc1, 0x8c, 0x86, 0xdb, 0x44, 0xe8, 0xbd, 0x5b, 0x96, 0xf3, 0x80, 0x77, 0xa3, 0x7e, - 0x4b, 0x81, 0xd9, 0x38, 0x9c, 0xb7, 0xf5, 0x1a, 0x14, 0x0c, 0xd3, 0xf4, 0xb0, 0xef, 0x0f, 0x9d, - 0x96, 0xab, 0x0c, 0x47, 0x0b, 0x91, 0x05, 0xce, 0x65, 0x46, 0xe6, 0x9c, 0xaa, 0xc3, 0xf4, 0x0d, - 0x1c, 0xdc, 0xc6, 0x81, 0x37, 0x56, 0x50, 0xbc, 0x41, 0xb6, 0x35, 0xb4, 0x32, 0x17, 0x8b, 0xf0, - 0x53, 0xfd, 0x54, 0x01, 0x24, 0xf6, 0x30, 0xce, 0x34, 0x8b, 0x5c, 0xce, 0xc4, 0xb9, 0xcc, 0xd2, - 0x92, 0x3a, 0x5d, 0xd7, 0xc1, 0x4e, 0x20, 0x3a, 0x62, 0xd5, 0x08, 0x1a, 0x66, 0x6a, 0xa0, 0x5b, - 0xae, 0x61, 0xae, 0x1a, 0xf6, 0x78, 0x8e, 0xc3, 0x19, 0x00, 0xdf, 0x6b, 0xe9, 0x5c, 0x8f, 0x33, - 0xdc, 0x2e, 0x79, 0xad, 0x3b, 0x4c, 0x95, 0xcf, 0x42, 0xd9, 0xf4, 0x03, 0x5e, 0x1c, 0xc6, 0x68, - 0xc1, 0xf4, 0x03, 0x56, 0x4e, 0x13, 0x82, 0x7d, 0x6c, 0xd8, 0xd8, 0xd4, 0x85, 0x10, 0xd7, 0x24, - 0x45, 0xab, 0xb3, 0x82, 0xcd, 0x08, 0x2e, 0x51, 0xae, 0x9c, 0x54, 0xb9, 0xee, 0xc3, 0xc2, 0x6d, - 0xc3, 0xe9, 0x19, 0xf6, 0x35, 0xb7, 0xd3, 0x35, 0x62, 0x39, 0xa4, 0x49, 0x43, 0xa9, 0x48, 0x0c, - 0xe5, 0xd3, 0x2c, 0xb5, 0x8d, 0x39, 0xe7, 0x74, 0x4c, 0x93, 0x9a, 0x00, 0x51, 0x7d, 0x68, 0x0c, - 0x36, 0x3f, 0xce, 0x84, 0x52, 0xa2, 0xc2, 0xa6, 0x44, 0xeb, 0xdd, 0x87, 0xa9, 0x6f, 0xc3, 0x53, - 0x34, 0xcd, 0x30, 0x04, 0xc5, 0x4e, 0xd5, 0x93, 0x0d, 0x28, 0x92, 0x06, 0x7e, 0x35, 0x43, 0x4d, - 0xe0, 0x40, 0x0b, 0xe3, 0x10, 0x7e, 0x25, 0x7e, 0x98, 0xfd, 0x6c, 0x4a, 0x76, 0x73, 0xbc, 0x47, - 0x6e, 0xac, 0x97, 0x60, 0x0a, 0x3f, 0xc2, 0xad, 0x5e, 0x60, 0x39, 0xed, 0x0d, 0xdb, 0x70, 0xee, - 0xb8, 0x7c, 0x49, 0x4a, 0x82, 0xd1, 0xb3, 0x50, 0x25, 0xdc, 0x77, 0x7b, 0x01, 0xc7, 0x63, 0x6b, - 0x53, 0x1c, 0x48, 0xda, 0x23, 0xe3, 0xb5, 0x71, 0x80, 0x4d, 0x8e, 0xc7, 0x16, 0xaa, 0x24, 0x78, - 0x80, 0x95, 0x04, 0xec, 0x1f, 0x86, 0x95, 0xff, 0xac, 0x24, 0x58, 0xc9, 0x5b, 0x38, 0x2e, 0x56, - 0xde, 0x04, 0xe8, 0x60, 0xaf, 0x8d, 0xd7, 0xa9, 0xf1, 0x67, 0x7b, 0xff, 0x25, 0xa9, 0xf1, 0xef, - 0x37, 0x70, 0x3b, 0xac, 0xa0, 0x09, 0x75, 0xd5, 0x1b, 0x30, 0x23, 0x41, 0x21, 0x76, 0xcd, 0x77, - 0x7b, 0x5e, 0x0b, 0x87, 0xc7, 0x47, 0xe1, 0x27, 0x59, 0x07, 0x03, 0xc3, 0x6b, 0xe3, 0x80, 0x0b, - 0x2d, 0xff, 0x52, 0x5f, 0xa3, 0xf1, 0x1f, 0x7a, 0xd4, 0x10, 0x93, 0xd4, 0x78, 0x2c, 0x5b, 0x19, - 0x88, 0x65, 0x6f, 0xd3, 0x60, 0x8b, 0x58, 0x6f, 0xcc, 0x3c, 0x84, 0x6d, 0xd2, 0x14, 0x36, 0xf9, - 0x15, 0x97, 0xf0, 0x53, 0xfd, 0x2f, 0x05, 0xaa, 0xeb, 0x9d, 0xae, 0xdb, 0x8f, 0x33, 0x8c, 0xbc, - 0x19, 0x1d, 0x3c, 0xa7, 0xcd, 0xc8, 0xce, 0x69, 0x9f, 0x81, 0x6a, 0xfc, 0x5e, 0x04, 0x3b, 0x19, - 0xaa, 0xb4, 0xc4, 0xfb, 0x10, 0xa7, 0xa0, 0xe4, 0xb9, 0x7b, 0x3a, 0x31, 0xa5, 0x26, 0xcf, 0x78, - 0x28, 0x7a, 0xee, 0x1e, 0x31, 0xb0, 0x26, 0x9a, 0x85, 0xdc, 0xb6, 0x65, 0x47, 0xc9, 0x3a, 0xec, - 0x03, 0xbd, 0x41, 0xb6, 0x6a, 0x2c, 0x22, 0x9a, 0x1f, 0x75, 0xc7, 0x14, 0xd6, 0x50, 0x3f, 0x84, - 0x5a, 0x38, 0xea, 0x31, 0xef, 0xf6, 0x04, 0x86, 0xff, 0x20, 0x4c, 0x46, 0x60, 0x1f, 0xea, 0x45, - 0x16, 0x28, 0xa3, 0xed, 0xc7, 0x26, 0x1d, 0xc1, 0x24, 0xc1, 0xe0, 0xba, 0x44, 0x7f, 0xab, 0xff, - 0x90, 0x81, 0xf9, 0x24, 0xf6, 0x38, 0x24, 0xbd, 0x16, 0xd7, 0x1f, 0xf9, 0xad, 0x0d, 0xb1, 0x37, - 0xae, 0x3b, 0x7c, 0x06, 0x5a, 0x6e, 0xcf, 0x09, 0xb8, 0x01, 0x22, 0x33, 0x70, 0x8d, 0x7c, 0xa3, - 0x05, 0x28, 0x58, 0xa6, 0x6e, 0x93, 0x5d, 0x1d, 0x5b, 0x93, 0xf2, 0x96, 0x79, 0x8b, 0xec, 0xf8, - 0x5e, 0x0f, 0x3d, 0xad, 0x91, 0x33, 0x18, 0x18, 0x3e, 0xaa, 0x41, 0xc6, 0x32, 0x79, 0x74, 0x23, - 0x63, 0x99, 0x44, 0x98, 0xe8, 0x71, 0x00, 0xcd, 0xb6, 0xe5, 0xe9, 0xb7, 0x44, 0x0a, 0xaa, 0x04, - 0xfa, 0x7e, 0x08, 0x24, 0xce, 0x18, 0x45, 0xe3, 0x21, 0x58, 0xea, 0x30, 0x17, 0xb5, 0x32, 0x81, - 0xad, 0x33, 0x90, 0xda, 0x80, 0x79, 0x42, 0x1a, 0x1b, 0xe2, 0x3d, 0x32, 0x21, 0xa1, 0x8b, 0xf5, - 0x3d, 0x05, 0x16, 0x06, 0x8a, 0xc6, 0xe1, 0xf5, 0x55, 0x71, 0xfa, 0xcb, 0x2b, 0x17, 0xa5, 0xa6, - 0x46, 0x3e, 0xb9, 0xa1, 0xac, 0x7c, 0x9f, 0xf9, 0x43, 0x1a, 0xcb, 0xb0, 0x7c, 0xcc, 0xf9, 0x3a, - 0x4b, 0x50, 0xdf, 0xb3, 0x82, 0x1d, 0x9d, 0xde, 0x03, 0xa2, 0xce, 0x08, 0x0b, 0x59, 0x17, 0xb5, - 0x1a, 0x81, 0x6f, 0x12, 0x30, 0x71, 0x48, 0x7c, 0xf5, 0xd7, 0x14, 0x98, 0x89, 0x91, 0x35, 0x0e, - 0x9b, 0xde, 0x24, 0x7e, 0x1a, 0x6b, 0x88, 0x73, 0x6a, 0x51, 0xca, 0x29, 0xde, 0x1b, 0x35, 0xc6, - 0x51, 0x0d, 0xf5, 0x5f, 0x14, 0x28, 0x0b, 0x25, 0x64, 0x03, 0xc8, 0xcb, 0xfa, 0x1b, 0xc0, 0x08, - 0x30, 0x12, 0x1b, 0x9e, 0x81, 0xbe, 0x89, 0x12, 0x32, 0xd6, 0x85, 0x94, 0x39, 0xd3, 0x47, 0x37, - 0xa1, 0xc6, 0xd8, 0x14, 0x91, 0x2e, 0x3d, 0x97, 0x89, 0x92, 0x01, 0x0d, 0xcf, 0xe4, 0x54, 0x6a, - 0x55, 0x5f, 0xf8, 0x62, 0xf1, 0x4b, 0xd7, 0xc4, 0xb4, 0xa7, 0xdc, 0xc0, 0x76, 0xac, 0x22, 0x56, - 0x25, 0x2e, 0xad, 0x8d, 0x0d, 0x13, 0x7b, 0xd1, 0xd8, 0xa2, 0x6f, 0xe2, 0x43, 0xb2, 0xdf, 0x3a, - 0x71, 0xf1, 0xb9, 0xb1, 0x05, 0x06, 0x22, 0xde, 0x3f, 0x7a, 0x0e, 0xa6, 0xcc, 0x4e, 0xec, 0x12, - 0x5a, 0xe8, 0xf4, 0x9a, 0x1d, 0xe1, 0xf6, 0x59, 0x8c, 0xa0, 0xc9, 0x38, 0x41, 0xff, 0xa9, 0x44, - 0xd7, 0x77, 0x3d, 0x6c, 0x62, 0x27, 0xb0, 0x0c, 0xfb, 0xe8, 0x32, 0xd9, 0x84, 0x62, 0xcf, 0xc7, - 0x9e, 0xb0, 0x36, 0x44, 0xdf, 0xa4, 0xac, 0x6b, 0xf8, 0xfe, 0x9e, 0xeb, 0x99, 0x9c, 0xca, 0xe8, - 0x7b, 0x48, 0xfe, 0x21, 0xbb, 0x08, 0x2a, 0xcf, 0x3f, 0x7c, 0x0d, 0x16, 0x3a, 0xae, 0x69, 0x6d, - 0x5b, 0xb2, 0xb4, 0x45, 0x52, 0x6d, 0x2e, 0x2c, 0x8e, 0xd5, 0x53, 0x7f, 0x90, 0x81, 0x85, 0x0f, - 0xba, 0xe6, 0x97, 0x30, 0xe6, 0x45, 0x28, 0xbb, 0xb6, 0xb9, 0x11, 0x1f, 0xb6, 0x08, 0x22, 0x18, - 0x0e, 0xde, 0x8b, 0x30, 0xd8, 0x61, 0xbc, 0x08, 0x1a, 0x9a, 0x9b, 0x79, 0x24, 0xde, 0xe4, 0x87, - 0xf1, 0xa6, 0x0d, 0x0b, 0x2c, 0x20, 0xfc, 0x98, 0x59, 0xa3, 0x7e, 0x04, 0x73, 0xc4, 0x34, 0x93, - 0x6e, 0x3e, 0xf0, 0xb1, 0x37, 0xa6, 0xc5, 0x39, 0x0d, 0xa5, 0xb0, 0xe5, 0x30, 0x6d, 0xb6, 0x0f, - 0x50, 0x6f, 0xc2, 0x6c, 0xa2, 0xaf, 0x23, 0x8e, 0x48, 0x5d, 0x04, 0xd0, 0x5c, 0x1b, 0xbf, 0xeb, - 0x04, 0x56, 0xb0, 0x4f, 0x96, 0x77, 0xc1, 0x5d, 0xa2, 0xbf, 0x09, 0x06, 0xe9, 0x63, 0x08, 0xc6, - 0x2f, 0xc2, 0x34, 0xd3, 0x38, 0xd2, 0xd2, 0xd1, 0x99, 0xfb, 0x3a, 0xe4, 0x31, 0xed, 0x84, 0x6f, - 0xf7, 0xcf, 0xca, 0x4d, 0x6c, 0x44, 0xad, 0xc6, 0xd1, 0xd5, 0x5f, 0x80, 0xa9, 0x35, 0xcf, 0xed, - 0x8e, 0xd7, 0x3b, 0xf5, 0x1e, 0x6c, 0x2c, 0xba, 0x81, 0x45, 0x02, 0xa0, 0xdb, 0xd0, 0xbf, 0x55, - 0x60, 0xfe, 0x6e, 0x17, 0x7b, 0x46, 0x80, 0x09, 0x2f, 0xc6, 0xeb, 0x69, 0x98, 0x7e, 0xc5, 0xa8, - 0xc8, 0xc6, 0xa9, 0x40, 0x6f, 0xc6, 0x6e, 0x62, 0xc9, 0xb7, 0x05, 0x09, 0x2a, 0x85, 0xf4, 0xee, - 0x3f, 0x56, 0x60, 0x7a, 0x13, 0x93, 0x35, 0x64, 0x3c, 0xf2, 0x2f, 0xc3, 0x24, 0xa1, 0x68, 0xd4, - 0x49, 0xa2, 0xc8, 0xe8, 0x02, 0x4c, 0x5b, 0x4e, 0xcb, 0xee, 0x99, 0x58, 0x27, 0x63, 0xd5, 0x89, - 0x0b, 0xc5, 0x17, 0xee, 0x29, 0x5e, 0x40, 0x48, 0x26, 0xcb, 0xa3, 0xfa, 0x88, 0x89, 0x64, 0x94, - 0x0d, 0xc3, 0xba, 0x53, 0x0e, 0xd3, 0xdd, 0xab, 0x90, 0x23, 0xdd, 0x84, 0x8b, 0xb5, 0xbc, 0x56, - 0x5f, 0xaa, 0x35, 0x86, 0xad, 0x7e, 0x5b, 0x01, 0x24, 0xb2, 0x68, 0x1c, 0x05, 0xfe, 0x9a, 0x18, - 0x17, 0xcf, 0x0e, 0x25, 0x9d, 0x8d, 0x34, 0x8a, 0x88, 0x0b, 0x33, 0x45, 0xa7, 0x71, 0x9c, 0x99, - 0x22, 0xe3, 0x1a, 0x3a, 0x53, 0x02, 0x13, 0x28, 0xb2, 0x38, 0x53, 0x54, 0x12, 0x25, 0x33, 0x45, - 0x68, 0x0e, 0x67, 0x8a, 0x51, 0x18, 0xce, 0x14, 0xed, 0x4e, 0x39, 0x4c, 0x77, 0xaf, 0x42, 0x8e, - 0x74, 0x73, 0x30, 0x93, 0xc2, 0x99, 0xa2, 0xd8, 0xea, 0x2f, 0x45, 0x33, 0xc5, 0x09, 0x18, 0xeb, - 0xfa, 0x48, 0x9e, 0x71, 0xfe, 0x40, 0x69, 0xe1, 0x13, 0xc5, 0xd1, 0xd5, 0x67, 0xa1, 0xa6, 0x61, - 0xb6, 0x7d, 0xee, 0x5b, 0x47, 0xe1, 0x84, 0x95, 0xe9, 0xdd, 0x79, 0x98, 0xda, 0xf0, 0xac, 0x5d, - 0xcb, 0xc6, 0xed, 0x61, 0x66, 0xf6, 0xaf, 0x14, 0x98, 0xe3, 0xb2, 0xc7, 0xdb, 0x3c, 0xfa, 0xc4, - 0xbf, 0x91, 0xb0, 0xa4, 0xcf, 0xa4, 0x38, 0xab, 0x22, 0xed, 0xa1, 0x35, 0x25, 0xcb, 0x73, 0x28, - 0x00, 0xdd, 0x90, 0x6e, 0x51, 0x0a, 0x66, 0x79, 0x69, 0x34, 0x28, 0x2a, 0x0a, 0x9f, 0x29, 0x7d, - 0x66, 0x70, 0x79, 0x78, 0x9b, 0x1e, 0x6e, 0x52, 0x08, 0xa7, 0x7d, 0x24, 0x3a, 0xa2, 0x4a, 0x68, - 0x0d, 0x20, 0xa2, 0x20, 0x14, 0x90, 0x67, 0xe5, 0x41, 0x98, 0x38, 0x83, 0x35, 0xa1, 0x1e, 0xbd, - 0xa1, 0x91, 0x64, 0xec, 0x78, 0xaf, 0x38, 0x24, 0x14, 0x7b, 0xf8, 0xa8, 0x92, 0xca, 0xfd, 0x13, - 0x85, 0xca, 0x83, 0xd3, 0xb2, 0xba, 0x86, 0xcd, 0xe5, 0xe1, 0x3c, 0xd4, 0xba, 0x21, 0x48, 0x3c, - 0xa2, 0xaf, 0x46, 0x50, 0x9a, 0xd7, 0xf4, 0xea, 0xa1, 0xf4, 0xf9, 0xe6, 0x44, 0xa4, 0x62, 0xcc, - 0x82, 0x66, 0x47, 0xb2, 0xa0, 0xa4, 0x1a, 0x41, 0x5f, 0x2d, 0x43, 0x29, 0xea, 0x9e, 0xec, 0xa6, - 0xaa, 0x37, 0x3c, 0xc3, 0x09, 0xdc, 0xd0, 0x11, 0x38, 0x92, 0xb6, 0xaf, 0xd2, 0x36, 0xd9, 0xcc, - 0xf0, 0x61, 0x8c, 0x36, 0xa1, 0xfd, 0x6a, 0xea, 0x7f, 0x2b, 0x50, 0xa6, 0xa4, 0x70, 0x42, 0x56, - 0x05, 0x3a, 0x39, 0x35, 0xa9, 0x6d, 0x8a, 0x5c, 0xd7, 0xfa, 0xd5, 0x62, 0xa2, 0x9a, 0x39, 0x8a, - 0xa8, 0x3e, 0x03, 0xd5, 0xf0, 0xb7, 0xb8, 0x76, 0x57, 0x42, 0x20, 0x5f, 0xbf, 0x0b, 0x6d, 0xc6, - 0x43, 0xba, 0x84, 0x97, 0x57, 0x54, 0xf9, 0x76, 0x5b, 0xe4, 0xb3, 0x16, 0x56, 0x51, 0x3f, 0x89, - 0x4c, 0x1e, 0x45, 0x38, 0xba, 0x75, 0xf8, 0x6a, 0xc2, 0x3a, 0x2c, 0xa6, 0x53, 0x91, 0x70, 0xb4, - 0xc8, 0x9e, 0x3a, 0x46, 0xc2, 0x98, 0x7b, 0x6a, 0xda, 0xac, 0x85, 0x87, 0xef, 0xa9, 0x45, 0x42, - 0xa2, 0x1a, 0xea, 0x4f, 0x15, 0x58, 0xe0, 0xbe, 0x4e, 0x24, 0x2b, 0xc7, 0xc0, 0x12, 0xf4, 0x75, - 0x6e, 0xf1, 0xb3, 0xd4, 0x27, 0x7b, 0x61, 0x98, 0x4f, 0x16, 0xd1, 0x29, 0x38, 0x65, 0xe7, 0xa1, - 0x74, 0x9b, 0x22, 0xbd, 0xfb, 0x28, 0x40, 0x0d, 0x28, 0xec, 0x62, 0xcf, 0xb7, 0x5c, 0x87, 0xeb, - 0x7f, 0xf8, 0x79, 0xe1, 0x1c, 0x14, 0xc3, 0xcb, 0x7a, 0xa8, 0x00, 0xd9, 0xab, 0xb6, 0x5d, 0x9f, - 0x40, 0x15, 0x28, 0xae, 0xf3, 0x1b, 0x69, 0x75, 0xe5, 0xc2, 0x3b, 0x30, 0x23, 0xf1, 0xfd, 0xd0, - 0x34, 0x54, 0xaf, 0x9a, 0x74, 0x93, 0x70, 0xcf, 0x25, 0xc0, 0xfa, 0x04, 0x9a, 0x07, 0xa4, 0xe1, - 0x8e, 0xbb, 0x4b, 0x11, 0xaf, 0x7b, 0x6e, 0x87, 0xc2, 0x95, 0x0b, 0x2f, 0xc2, 0xac, 0x8c, 0x52, - 0x54, 0x82, 0x1c, 0x1d, 0x79, 0x7d, 0x02, 0x01, 0xe4, 0x35, 0xbc, 0xeb, 0x3e, 0xc0, 0x75, 0x65, - 0xe5, 0x87, 0x17, 0xa1, 0xca, 0x68, 0xe7, 0x57, 0xcb, 0x91, 0x0e, 0xf5, 0xe4, 0xc3, 0x59, 0xe8, - 0x2b, 0xf2, 0xc3, 0x6b, 0xf9, 0xfb, 0x5a, 0xcd, 0x61, 0x82, 0xa3, 0x4e, 0xa0, 0x0f, 0xa1, 0x16, - 0x7f, 0x75, 0x0a, 0xc9, 0x63, 0xf2, 0xd2, 0xa7, 0xa9, 0x0e, 0x6a, 0x5c, 0x87, 0x6a, 0xec, 0xed, - 0x28, 0x24, 0x9f, 0x4c, 0xd9, 0xfb, 0x52, 0x4d, 0xf9, 0x91, 0x8a, 0xf8, 0xac, 0x13, 0xa3, 0x3e, - 0xfe, 0x9c, 0x4b, 0x0a, 0xf5, 0xd2, 0x37, 0x5f, 0x0e, 0xa2, 0xde, 0x80, 0xe9, 0x81, 0xd7, 0x56, - 0xd0, 0x8b, 0x29, 0x46, 0x4c, 0xfe, 0x2a, 0xcb, 0x41, 0x5d, 0xec, 0x01, 0x1a, 0x7c, 0x11, 0x09, - 0x2d, 0xcb, 0x67, 0x20, 0xed, 0x61, 0xa8, 0xe6, 0xa5, 0x91, 0xf1, 0x23, 0xc6, 0xfd, 0x8a, 0x02, - 0x0b, 0x29, 0x0f, 0x73, 0xa0, 0xcb, 0x69, 0x27, 0x96, 0x43, 0x9e, 0x19, 0x69, 0xbe, 0x72, 0xb8, - 0x4a, 0x11, 0x21, 0x0e, 0x4c, 0x25, 0x1e, 0xa9, 0x40, 0x17, 0x53, 0x6f, 0xd6, 0x0e, 0x3e, 0xda, - 0xd1, 0xfc, 0xca, 0x68, 0xc8, 0x51, 0x7f, 0xf7, 0x61, 0x2a, 0xf1, 0x42, 0x43, 0x4a, 0x7f, 0xf2, - 0x77, 0x1c, 0x0e, 0x9a, 0xd0, 0x6f, 0x42, 0x35, 0xf6, 0x94, 0x42, 0x8a, 0xc4, 0xcb, 0x9e, 0x5b, - 0x38, 0xa8, 0xe9, 0xfb, 0x50, 0x11, 0x5f, 0x3c, 0x40, 0x4b, 0x69, 0xba, 0x34, 0xd0, 0xf0, 0x61, - 0x54, 0xa9, 0x7f, 0x53, 0x79, 0x88, 0x2a, 0x0d, 0x5c, 0xee, 0x1e, 0x5d, 0x95, 0x84, 0xf6, 0x87, - 0xaa, 0xd2, 0xa1, 0xbb, 0xf8, 0x96, 0x42, 0x43, 0x26, 0x92, 0x9b, 0xf0, 0x68, 0x25, 0x4d, 0x36, - 0xd3, 0xef, 0xfc, 0x37, 0x2f, 0x1f, 0xaa, 0x4e, 0xc4, 0xc5, 0x07, 0x50, 0x8b, 0xdf, 0xf7, 0x4e, - 0xe1, 0xa2, 0xf4, 0x8a, 0x7c, 0xf3, 0xe2, 0x48, 0xb8, 0x51, 0x67, 0x1f, 0x40, 0x59, 0x78, 0x0b, - 0x13, 0x3d, 0x3f, 0x44, 0x8e, 0xc5, 0x87, 0x21, 0x0f, 0xe2, 0xe4, 0xfb, 0x50, 0x8a, 0x9e, 0xb0, - 0x44, 0xe7, 0x53, 0xe5, 0xf7, 0x30, 0x4d, 0x6e, 0x02, 0xf4, 0xdf, 0xa7, 0x44, 0xcf, 0x49, 0xdb, - 0x1c, 0x78, 0xc0, 0xf2, 0xa0, 0x46, 0xa3, 0xe1, 0xb3, 0x6b, 0x34, 0xc3, 0x86, 0x2f, 0xde, 0xfb, - 0x3a, 0xa8, 0xd9, 0x1d, 0xa8, 0xc6, 0x6e, 0x6b, 0xa6, 0xa9, 0xb0, 0xe4, 0x12, 0x6d, 0xf3, 0xc2, - 0x28, 0xa8, 0xd1, 0xfc, 0xed, 0x40, 0x35, 0x76, 0x77, 0x2e, 0xa5, 0x27, 0xd9, 0x55, 0xc1, 0x94, - 0x9e, 0xa4, 0x57, 0xf1, 0xd4, 0x09, 0xf4, 0x89, 0x70, 0x4d, 0x2f, 0x76, 0x15, 0x12, 0xbd, 0x3c, - 0xb4, 0x1d, 0xd9, 0x4d, 0xd0, 0xe6, 0xca, 0x61, 0xaa, 0x44, 0x24, 0x70, 0xa9, 0x62, 0x2c, 0x4d, - 0x97, 0xaa, 0xc3, 0xcc, 0xd4, 0x26, 0xe4, 0xd9, 0x6d, 0x38, 0xa4, 0xa6, 0xdc, 0x7b, 0x15, 0xae, - 0xca, 0x35, 0xe5, 0xdb, 0x8f, 0xf8, 0x45, 0x31, 0xd6, 0x28, 0x3b, 0xdc, 0x4e, 0x69, 0x34, 0x76, - 0x15, 0x6a, 0xd4, 0x46, 0x35, 0xc8, 0xb3, 0xdb, 0x1a, 0x29, 0x8d, 0xc6, 0x6e, 0x20, 0x35, 0x87, - 0xe3, 0xb0, 0x3d, 0xef, 0x04, 0xda, 0x80, 0x1c, 0xcd, 0x04, 0x40, 0xe7, 0x86, 0x5d, 0x64, 0x18, - 0xd6, 0x62, 0xec, 0xae, 0x83, 0x3a, 0x81, 0xee, 0x42, 0x8e, 0x06, 0x55, 0x53, 0x5a, 0x14, 0x6f, - 0x23, 0x34, 0x87, 0xa2, 0x84, 0x24, 0x9a, 0x50, 0x11, 0x53, 0x90, 0x53, 0x96, 0x2c, 0x49, 0x92, - 0x76, 0x73, 0x14, 0xcc, 0xb0, 0x17, 0xa6, 0x46, 0xfd, 0xac, 0x88, 0x74, 0x35, 0x1a, 0xc8, 0xb8, - 0x48, 0x57, 0xa3, 0xc1, 0x24, 0x0b, 0x75, 0x02, 0xfd, 0xba, 0x02, 0x8d, 0xb4, 0xbc, 0x58, 0x94, - 0xea, 0x01, 0x0d, 0x4b, 0xee, 0x6d, 0xbe, 0x7a, 0xc8, 0x5a, 0x11, 0x2d, 0x1f, 0xd3, 0x58, 0xec, - 0x40, 0x26, 0xec, 0xa5, 0xb4, 0xf6, 0x52, 0xb2, 0x3b, 0x9b, 0x2f, 0x8d, 0x5e, 0x21, 0xea, 0x7b, - 0x0b, 0xca, 0x42, 0x1c, 0x38, 0xc5, 0xf2, 0x0e, 0x06, 0xb0, 0x53, 0x66, 0x55, 0x12, 0x52, 0x66, - 0xe2, 0x4d, 0xd3, 0x27, 0x53, 0x84, 0x51, 0xcc, 0xc6, 0x4c, 0x11, 0xef, 0x58, 0xf6, 0xa5, 0x3a, - 0x81, 0x30, 0x54, 0xc4, 0x5c, 0xca, 0x14, 0x69, 0x94, 0xa4, 0x61, 0x36, 0x5f, 0x18, 0x01, 0x33, - 0xea, 0x46, 0x07, 0xe8, 0xe7, 0x32, 0xa6, 0xac, 0x75, 0x03, 0xe9, 0x94, 0xcd, 0xe7, 0x0f, 0xc4, - 0x13, 0x97, 0x7d, 0x21, 0x3b, 0x31, 0x85, 0xfb, 0x83, 0xf9, 0x8b, 0x23, 0xec, 0x45, 0x06, 0x33, - 0xe0, 0x52, 0xf6, 0x22, 0xa9, 0xc9, 0x76, 0xcd, 0x4b, 0x23, 0xe3, 0x47, 0xe3, 0x79, 0x08, 0xf5, - 0x64, 0xc6, 0x60, 0xca, 0x1e, 0x37, 0x25, 0x6f, 0xb1, 0xf9, 0xe2, 0x88, 0xd8, 0xe2, 0x7a, 0x78, - 0x6a, 0x90, 0xa6, 0xff, 0x67, 0x05, 0x3b, 0x34, 0x59, 0x6d, 0x94, 0x51, 0x8b, 0x79, 0x71, 0xa3, - 0x8c, 0x3a, 0x96, 0x05, 0xc7, 0x17, 0x2f, 0x9a, 0x01, 0x92, 0xb6, 0x78, 0x89, 0xf9, 0x57, 0x29, - 0xeb, 0x4c, 0x3c, 0x5b, 0x89, 0xb9, 0x9f, 0xf1, 0xcc, 0x12, 0x74, 0x61, 0xa4, 0xf4, 0x93, 0x61, - 0xee, 0xa7, 0x3c, 0x55, 0x85, 0x6d, 0xdd, 0x12, 0x89, 0x33, 0x29, 0x5b, 0x29, 0x79, 0xe6, 0x4d, - 0xca, 0xd6, 0x2d, 0x25, 0x17, 0x87, 0x2a, 0x56, 0x3d, 0x99, 0x85, 0x30, 0xfc, 0x2c, 0x24, 0x19, - 0x9d, 0x3e, 0xf8, 0xb8, 0xa2, 0x9e, 0x0c, 0xf9, 0xa7, 0x74, 0x90, 0x92, 0x19, 0x30, 0x42, 0x07, - 0xc9, 0xc0, 0x79, 0x4a, 0x07, 0x29, 0xf1, 0xf5, 0x11, 0x7c, 0xd7, 0x58, 0x10, 0x3b, 0x65, 0x29, - 0x94, 0x05, 0xba, 0x53, 0x96, 0x42, 0x69, 0xfc, 0x9d, 0x79, 0xf4, 0xfd, 0x00, 0x75, 0x8a, 0x95, - 0x1b, 0x88, 0x60, 0x1f, 0x44, 0xfe, 0x5d, 0x28, 0x86, 0x51, 0x67, 0xf4, 0x6c, 0xaa, 0x8b, 0x78, - 0x88, 0x06, 0xef, 0xc3, 0x54, 0xe2, 0x04, 0x2f, 0x45, 0x44, 0xe5, 0x91, 0xe8, 0x83, 0xe7, 0x13, - 0xfa, 0xb1, 0xcd, 0x14, 0x26, 0x0c, 0xc4, 0x87, 0x53, 0x4c, 0xfd, 0x60, 0x90, 0x54, 0xec, 0x80, - 0x10, 0x36, 0xb4, 0x03, 0x21, 0xac, 0x39, 0xb4, 0x03, 0x31, 0xb6, 0xc7, 0xf7, 0xab, 0xb1, 0x40, - 0x4e, 0xda, 0x7e, 0x55, 0x16, 0x46, 0x4b, 0xdb, 0xaf, 0x4a, 0x23, 0x43, 0x4c, 0xfc, 0x93, 0xa7, - 0xa1, 0x29, 0xe2, 0x9f, 0x72, 0x0c, 0x7d, 0xd0, 0x7c, 0x6c, 0x41, 0x59, 0x38, 0x4b, 0x47, 0xc3, - 0xf8, 0x20, 0x1e, 0xf8, 0xa7, 0xf8, 0x25, 0x92, 0x63, 0x79, 0x75, 0x62, 0xa5, 0x07, 0x95, 0x0d, - 0xcf, 0x7d, 0x14, 0x3e, 0xfe, 0xf9, 0x25, 0x79, 0x15, 0x57, 0x5a, 0x50, 0x63, 0x08, 0x3a, 0x7e, - 0x14, 0xe8, 0xee, 0xd6, 0x47, 0xe8, 0xf4, 0x32, 0xfb, 0xb7, 0x8c, 0xe5, 0xf0, 0xdf, 0x32, 0x96, - 0xaf, 0x5b, 0x36, 0xbe, 0xcb, 0xb3, 0x5f, 0xff, 0xad, 0x30, 0xe4, 0xee, 0x65, 0x74, 0x3e, 0xae, - 0xf1, 0x3f, 0xec, 0x78, 0xf7, 0x51, 0x70, 0x77, 0xeb, 0xa3, 0x55, 0xe3, 0xf3, 0xb7, 0x0a, 0x90, - 0x5b, 0x59, 0x7e, 0x79, 0xf9, 0x25, 0xa8, 0x59, 0x11, 0x7a, 0xdb, 0xeb, 0xb6, 0x56, 0xcb, 0xac, - 0xd2, 0x06, 0x69, 0x67, 0x43, 0xf9, 0xff, 0x97, 0xdb, 0x56, 0xb0, 0xd3, 0xdb, 0x22, 0x53, 0x70, - 0x89, 0xa1, 0xbd, 0x68, 0xb9, 0xfc, 0xd7, 0x25, 0xcb, 0x09, 0xb0, 0xe7, 0x18, 0x36, 0xfb, 0x23, - 0x0f, 0x0e, 0xed, 0x6e, 0xfd, 0x9e, 0xa2, 0x6c, 0xe5, 0x29, 0xe8, 0xf2, 0xff, 0x05, 0x00, 0x00, - 0xff, 0xff, 0x6d, 0x7d, 0xfb, 0x5c, 0x2a, 0x64, 0x00, 0x00, + // 5101 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3d, 0x5b, 0x6c, 0x1c, 0x47, + 0x72, 0x9c, 0x5d, 0xee, 0xab, 0xf6, 0xc1, 0x65, 0xf3, 0xb5, 0x5e, 0x49, 0x16, 0x35, 0xb6, 0xce, + 0xb4, 0x74, 0xa2, 0x2c, 0xca, 0x96, 0xcf, 0xb2, 0xcf, 0xb6, 0x24, 0x5a, 0x12, 0x61, 0x3d, 0xe8, + 0xa1, 0xec, 0xe0, 0x62, 0x18, 0x93, 0xe1, 0x4e, 0x73, 0x39, 0xd6, 0xec, 0xcc, 0x6a, 0x66, 0x96, + 0x14, 0xfd, 0x11, 0x18, 0xb8, 0x4b, 0x72, 0x41, 0x9c, 0x3b, 0x1c, 0x72, 0xc8, 0xe1, 0x3e, 0xf2, + 0x40, 0x90, 0x04, 0x08, 0x70, 0x09, 0x72, 0x49, 0x80, 0x00, 0xc9, 0x47, 0x12, 0xe0, 0x3e, 0x02, + 0x23, 0x48, 0x2e, 0x5f, 0x41, 0x90, 0x7c, 0x1e, 0x02, 0xe4, 0x2f, 0x01, 0xee, 0x33, 0x41, 0x82, + 0x7e, 0xcc, 0x6c, 0xcf, 0x6c, 0xcf, 0x72, 0xc9, 0x3d, 0x99, 0x14, 0xbf, 0xb6, 0xab, 0xab, 0xbb, + 0xab, 0xab, 0xab, 0xab, 0xaa, 0xbb, 0xaa, 0x87, 0x50, 0xe9, 0x58, 0xf6, 0x4e, 0xcf, 0x5f, 0xee, + 0x7a, 0x6e, 0xe0, 0xa2, 0x19, 0xb1, 0xb4, 0xcc, 0x0a, 0xcd, 0x4a, 0xcb, 0xed, 0x74, 0x5c, 0x87, + 0x01, 0x9b, 0x15, 0xbf, 0xb5, 0x8d, 0x3b, 0x06, 0x2f, 0x2d, 0xb6, 0x5d, 0xb7, 0x6d, 0xe3, 0x8b, + 0xb4, 0xb4, 0xd9, 0xdb, 0xba, 0x68, 0x62, 0xbf, 0xe5, 0x59, 0xdd, 0xc0, 0xf5, 0x18, 0x86, 0xfa, + 0xdb, 0x0a, 0xa0, 0x1b, 0x1e, 0x36, 0x02, 0x7c, 0xcd, 0xb6, 0x0c, 0x5f, 0xc3, 0x8f, 0x7a, 0xd8, + 0x0f, 0xd0, 0x4b, 0x30, 0xb9, 0x69, 0xf8, 0xb8, 0xa1, 0x2c, 0x2a, 0x4b, 0xe5, 0x95, 0x93, 0xcb, + 0xb1, 0x81, 0xf9, 0x80, 0x77, 0xfd, 0xf6, 0x75, 0xc3, 0xc7, 0x1a, 0xc5, 0x44, 0x0b, 0x50, 0x30, + 0x37, 0x75, 0xc7, 0xe8, 0xe0, 0x46, 0x66, 0x51, 0x59, 0x2a, 0x69, 0x79, 0x73, 0xf3, 0x9e, 0xd1, + 0xc1, 0xe8, 0x05, 0x98, 0x6a, 0xb9, 0xb6, 0x8d, 0x5b, 0x81, 0xe5, 0x3a, 0x0c, 0x21, 0x4b, 0x11, + 0x6a, 0x7d, 0x30, 0x45, 0x9c, 0x85, 0x9c, 0x41, 0x68, 0x68, 0x4c, 0xd2, 0x6a, 0x56, 0x50, 0x7d, + 0xa8, 0xaf, 0x7a, 0x6e, 0xf7, 0x49, 0x51, 0x17, 0x0d, 0x9a, 0x15, 0x07, 0xfd, 0x2d, 0x05, 0xa6, + 0xaf, 0xd9, 0x01, 0xf6, 0x8e, 0x29, 0x53, 0x7e, 0x90, 0x81, 0x05, 0xb6, 0x6a, 0x37, 0x22, 0xf4, + 0xa3, 0xa4, 0x72, 0x1e, 0xf2, 0x4c, 0xee, 0x28, 0x99, 0x15, 0x8d, 0x97, 0xd0, 0x29, 0x00, 0x7f, + 0xdb, 0xf0, 0x4c, 0x5f, 0x77, 0x7a, 0x9d, 0x46, 0x6e, 0x51, 0x59, 0xca, 0x69, 0x25, 0x06, 0xb9, + 0xd7, 0xeb, 0x20, 0x0d, 0xa6, 0x5b, 0xae, 0xe3, 0x5b, 0x7e, 0x80, 0x9d, 0xd6, 0x9e, 0x6e, 0xe3, + 0x1d, 0x6c, 0x37, 0xf2, 0x8b, 0xca, 0x52, 0x6d, 0xe5, 0xac, 0x94, 0xee, 0x1b, 0x7d, 0xec, 0x3b, + 0x04, 0x59, 0xab, 0xb7, 0x12, 0x90, 0xab, 0xe8, 0xf3, 0x37, 0xa7, 0x8a, 0x4a, 0x5d, 0x69, 0xfc, + 0x5f, 0xf8, 0xa7, 0xa8, 0xbf, 0xa3, 0xc0, 0x1c, 0x11, 0xa2, 0x63, 0xc1, 0xac, 0x90, 0xc2, 0x8c, + 0x48, 0xe1, 0x1f, 0x29, 0x30, 0x7b, 0xdb, 0xf0, 0x8f, 0xc7, 0x6a, 0x9e, 0x02, 0x08, 0xac, 0x0e, + 0xd6, 0xfd, 0xc0, 0xe8, 0x74, 0xe9, 0x8a, 0x4e, 0x6a, 0x25, 0x02, 0xd9, 0x20, 0x00, 0xf5, 0x6b, + 0x50, 0xb9, 0xee, 0xba, 0xb6, 0x86, 0xfd, 0xae, 0xeb, 0xf8, 0x18, 0x5d, 0x86, 0xbc, 0x1f, 0x18, + 0x41, 0xcf, 0xe7, 0x44, 0x9e, 0x90, 0x12, 0xb9, 0x41, 0x51, 0x34, 0x8e, 0x4a, 0xe4, 0x7a, 0xc7, + 0xb0, 0x7b, 0x8c, 0xc6, 0xa2, 0xc6, 0x0a, 0xea, 0x87, 0x50, 0xdb, 0x08, 0x3c, 0xcb, 0x69, 0xff, + 0x0c, 0x3b, 0x2f, 0x85, 0x9d, 0xff, 0x87, 0x02, 0xcf, 0xac, 0x52, 0xfd, 0xb7, 0x79, 0x4c, 0xb6, + 0x8d, 0x0a, 0x95, 0x3e, 0x64, 0x6d, 0x95, 0xb2, 0x3a, 0xab, 0xc5, 0x60, 0x89, 0xc5, 0xc8, 0x25, + 0x16, 0x23, 0x14, 0xa6, 0xac, 0x28, 0x4c, 0x9f, 0xe6, 0xa0, 0x29, 0x9b, 0xe8, 0x38, 0x2c, 0xfd, + 0x6a, 0xb4, 0xc3, 0x33, 0xb4, 0x51, 0x62, 0x7f, 0x72, 0xab, 0xd3, 0x1f, 0x6d, 0x83, 0x02, 0x22, + 0x45, 0x90, 0x9c, 0x69, 0x56, 0x32, 0xd3, 0x15, 0x98, 0xdb, 0xb1, 0xbc, 0xa0, 0x67, 0xd8, 0x7a, + 0x6b, 0xdb, 0x70, 0x1c, 0x6c, 0x53, 0xde, 0x11, 0xd5, 0x97, 0x5d, 0x2a, 0x69, 0x33, 0xbc, 0xf2, + 0x06, 0xab, 0x23, 0x0c, 0xf4, 0xd1, 0xcb, 0x30, 0xdf, 0xdd, 0xde, 0xf3, 0xad, 0xd6, 0x40, 0xa3, + 0x1c, 0x6d, 0x34, 0x1b, 0xd6, 0xc6, 0x5a, 0x9d, 0x87, 0xe9, 0x16, 0xd5, 0x9e, 0xa6, 0x4e, 0x38, + 0xc9, 0x58, 0x9b, 0xa7, 0xac, 0xad, 0xf3, 0x8a, 0x07, 0x21, 0x9c, 0x90, 0x15, 0x22, 0xf7, 0x82, + 0x96, 0xd0, 0xa0, 0x40, 0x1b, 0xcc, 0xf0, 0xca, 0xf7, 0x83, 0x56, 0xbf, 0x4d, 0x5c, 0xef, 0x15, + 0x93, 0x7a, 0xaf, 0x01, 0x05, 0xaa, 0xc7, 0xb1, 0xdf, 0x28, 0x51, 0x32, 0xc3, 0x22, 0x5a, 0x83, + 0x29, 0x3f, 0x30, 0xbc, 0x40, 0xef, 0xba, 0xbe, 0x45, 0xf8, 0xe2, 0x37, 0x60, 0x31, 0xbb, 0x54, + 0x5e, 0x59, 0x94, 0x2e, 0xd2, 0xbb, 0x78, 0x6f, 0xd5, 0x08, 0x8c, 0x75, 0xc3, 0xf2, 0xb4, 0x1a, + 0x6d, 0xb8, 0x1e, 0xb6, 0x93, 0x2b, 0xd7, 0xf2, 0x58, 0xca, 0x55, 0x26, 0xd9, 0x15, 0x99, 0x64, + 0xab, 0x7f, 0xad, 0xc0, 0xdc, 0x1d, 0xd7, 0x30, 0x8f, 0xc7, 0x3e, 0x3b, 0x0b, 0x35, 0x0f, 0x77, + 0x6d, 0xab, 0x65, 0x90, 0xf5, 0xd8, 0xc4, 0x1e, 0xdd, 0x69, 0x39, 0xad, 0xca, 0xa1, 0xf7, 0x28, + 0xf0, 0x6a, 0xe1, 0xf3, 0x37, 0x27, 0xeb, 0xb9, 0x46, 0x56, 0xfd, 0x9e, 0x02, 0x0d, 0x0d, 0xdb, + 0xd8, 0xf0, 0x8f, 0x87, 0xa2, 0x60, 0x94, 0xe5, 0x1b, 0x59, 0xf5, 0x27, 0x0a, 0xcc, 0xde, 0xc2, + 0x01, 0xd9, 0x9c, 0x96, 0x1f, 0x58, 0xad, 0x23, 0xf5, 0x4d, 0x5e, 0x80, 0xa9, 0xae, 0xe1, 0x05, + 0x56, 0x84, 0x17, 0x6e, 0xd5, 0x5a, 0x04, 0x66, 0xfb, 0xed, 0x22, 0xcc, 0xb4, 0x7b, 0x86, 0x67, + 0x38, 0x01, 0xc6, 0xc2, 0x06, 0x62, 0xca, 0x0c, 0x45, 0x55, 0xd1, 0xfe, 0x51, 0x7f, 0x49, 0x81, + 0xb9, 0xc4, 0x34, 0xc7, 0x51, 0x5e, 0xaf, 0x42, 0x8e, 0xfc, 0xf2, 0x1b, 0x19, 0xba, 0x97, 0xce, + 0xa4, 0xed, 0xa5, 0x0f, 0x88, 0x9d, 0xa0, 0x9b, 0x89, 0xe1, 0xab, 0xdf, 0x55, 0xe0, 0xd9, 0x5b, + 0x38, 0x10, 0xd4, 0xda, 0x71, 0x60, 0xbc, 0xfa, 0x6d, 0x05, 0x4e, 0xa7, 0x92, 0x75, 0x24, 0x8c, + 0xfa, 0xa9, 0x02, 0xf3, 0x1b, 0xdb, 0xee, 0x6e, 0x9f, 0xa4, 0x27, 0xc1, 0xa0, 0xb8, 0x2d, 0xcc, + 0x26, 0x6c, 0x21, 0xba, 0x04, 0x93, 0xc1, 0x5e, 0x17, 0xd3, 0xcd, 0x5d, 0x5b, 0x39, 0xb5, 0x2c, + 0x39, 0x2d, 0x2d, 0x13, 0x22, 0x1f, 0xec, 0x75, 0xb1, 0x46, 0x51, 0xd1, 0x8b, 0x50, 0x4f, 0xb0, + 0x3c, 0xb4, 0x1c, 0x53, 0x71, 0x9e, 0xfb, 0xa1, 0xa5, 0x9d, 0x14, 0x2d, 0xed, 0x7f, 0x65, 0x60, + 0x61, 0x60, 0xda, 0xe3, 0x2c, 0x80, 0x8c, 0x9e, 0x8c, 0x94, 0x1e, 0xa2, 0xd4, 0x04, 0x54, 0xcb, + 0x24, 0x47, 0x98, 0xec, 0x52, 0x56, 0xab, 0x0a, 0x46, 0xd5, 0xf4, 0xd1, 0x05, 0x40, 0x03, 0xb6, + 0x8e, 0xed, 0xd3, 0x49, 0x6d, 0x3a, 0x69, 0xec, 0xa8, 0x41, 0x95, 0x5a, 0x3b, 0xc6, 0x96, 0x49, + 0x6d, 0x56, 0x62, 0xee, 0x7c, 0x74, 0x09, 0x66, 0x2d, 0xe7, 0x2e, 0xee, 0xb8, 0xde, 0x9e, 0xde, + 0xc5, 0x5e, 0x0b, 0x3b, 0x81, 0xd1, 0xc6, 0x7e, 0x23, 0x4f, 0x29, 0x9a, 0x09, 0xeb, 0xd6, 0xfb, + 0x55, 0xe8, 0x0a, 0x2c, 0x3c, 0xea, 0x61, 0x6f, 0x4f, 0xf7, 0xb1, 0xb7, 0x63, 0xb5, 0xb0, 0x6e, + 0xec, 0x18, 0x96, 0x6d, 0x6c, 0xda, 0xb8, 0x51, 0x58, 0xcc, 0x2e, 0x15, 0xb5, 0x39, 0x5a, 0xbd, + 0xc1, 0x6a, 0xaf, 0x85, 0x95, 0xea, 0x9f, 0x2b, 0x30, 0xcf, 0x8e, 0x3e, 0xeb, 0xa1, 0x92, 0x39, + 0x62, 0xd3, 0x12, 0xd7, 0x81, 0xfc, 0xa0, 0x56, 0x8d, 0xa9, 0x40, 0xf5, 0x87, 0x0a, 0xcc, 0x92, + 0x13, 0xc8, 0xd3, 0x44, 0xf3, 0x9f, 0x2a, 0x30, 0x73, 0xdb, 0xf0, 0x9f, 0x26, 0x92, 0xff, 0x8d, + 0xbb, 0x1d, 0x11, 0xcd, 0x4f, 0x87, 0x7d, 0x1c, 0xf4, 0x4f, 0x72, 0x12, 0xff, 0x44, 0xfd, 0xcb, + 0xbe, 0x5b, 0xf2, 0x74, 0x4d, 0x50, 0xfd, 0x2b, 0x05, 0x4e, 0xdd, 0xc2, 0x41, 0x44, 0xf5, 0xf1, + 0xf0, 0x5f, 0x46, 0x14, 0xaa, 0x6f, 0x31, 0x27, 0x40, 0x4a, 0xfc, 0x91, 0x18, 0xdb, 0x5f, 0xcb, + 0xc0, 0x1c, 0xb1, 0x3a, 0xc7, 0x43, 0x08, 0x46, 0x39, 0xc4, 0x4a, 0x04, 0x25, 0x27, 0xdd, 0x09, + 0xa1, 0x09, 0xcf, 0x8f, 0x6c, 0xc2, 0xd5, 0x3f, 0xcb, 0x30, 0xd7, 0x43, 0xe4, 0xc6, 0x38, 0xcb, + 0x22, 0xa1, 0x35, 0x23, 0xa5, 0x55, 0x85, 0x4a, 0x04, 0x59, 0x5b, 0x0d, 0xcd, 0x6f, 0x0c, 0x76, + 0x5c, 0xad, 0xaf, 0xfa, 0x99, 0x02, 0xf3, 0xe1, 0x15, 0xc1, 0x06, 0x6e, 0x77, 0xb0, 0x13, 0x1c, + 0x5e, 0x86, 0x92, 0x12, 0x90, 0x91, 0x48, 0xc0, 0x49, 0x28, 0xf9, 0x6c, 0x9c, 0xe8, 0xf4, 0xdf, + 0x07, 0xa8, 0x7f, 0xa3, 0xc0, 0xc2, 0x00, 0x39, 0xe3, 0x2c, 0x62, 0x03, 0x0a, 0x96, 0x63, 0xe2, + 0xc7, 0x11, 0x35, 0x61, 0x91, 0xd4, 0x6c, 0xf6, 0x2c, 0xdb, 0x8c, 0xc8, 0x08, 0x8b, 0xe8, 0x0c, + 0x54, 0xb0, 0x43, 0x7c, 0x0c, 0x9d, 0xe2, 0x52, 0x41, 0x2e, 0x6a, 0x65, 0x06, 0x5b, 0x23, 0x20, + 0xd2, 0x78, 0xcb, 0xc2, 0xb4, 0x71, 0x8e, 0x35, 0xe6, 0x45, 0xf5, 0xd7, 0x15, 0x98, 0x21, 0x52, + 0xc8, 0xa9, 0xf7, 0x9f, 0x2c, 0x37, 0x17, 0xa1, 0x2c, 0x88, 0x19, 0x9f, 0x88, 0x08, 0x52, 0x1f, + 0xc2, 0x6c, 0x9c, 0x9c, 0x71, 0xb8, 0xf9, 0x2c, 0x40, 0xb4, 0x56, 0x6c, 0x37, 0x64, 0x35, 0x01, + 0xa2, 0x7e, 0x96, 0x09, 0x83, 0x08, 0x94, 0x4d, 0x47, 0x7c, 0x77, 0x49, 0x97, 0x44, 0xd4, 0xe7, + 0x25, 0x0a, 0xa1, 0xd5, 0xab, 0x50, 0xc1, 0x8f, 0x03, 0xcf, 0xd0, 0xbb, 0x86, 0x67, 0x74, 0xd8, + 0xb6, 0x1a, 0x49, 0xf5, 0x96, 0x69, 0xb3, 0x75, 0xda, 0x8a, 0x0c, 0x42, 0x45, 0x84, 0x0d, 0x92, + 0x67, 0x83, 0x50, 0x08, 0x35, 0x18, 0x7f, 0x4f, 0x9c, 0x3d, 0x2e, 0xcd, 0xc7, 0x9d, 0x21, 0xf1, + 0xa9, 0xe4, 0x92, 0x53, 0xf9, 0x03, 0x05, 0xea, 0x74, 0x0a, 0xab, 0x3c, 0x70, 0x64, 0xb9, 0x4e, + 0xa2, 0x8d, 0x92, 0x68, 0x33, 0x64, 0xef, 0xbd, 0x06, 0x79, 0xce, 0xf7, 0xec, 0xa8, 0x7c, 0xe7, + 0x0d, 0xf6, 0x99, 0x86, 0xfa, 0x7b, 0x0a, 0xcc, 0x25, 0x58, 0x3e, 0x8e, 0xc0, 0x3f, 0x00, 0xc4, + 0x66, 0x68, 0xf6, 0xa7, 0x1d, 0xda, 0xe9, 0xb3, 0x52, 0xa3, 0x94, 0x64, 0x92, 0x36, 0x6d, 0x25, + 0x20, 0xbe, 0xfa, 0x63, 0x05, 0x4e, 0xde, 0xc2, 0x01, 0x45, 0xbd, 0x4e, 0x94, 0xce, 0xba, 0xe7, + 0xb6, 0x3d, 0xec, 0xfb, 0x4f, 0xaf, 0x7c, 0xfc, 0x26, 0x73, 0xec, 0x64, 0x53, 0x1a, 0x87, 0xff, + 0x67, 0xa0, 0x42, 0xc7, 0xc0, 0xa6, 0xee, 0xb9, 0xbb, 0x3e, 0x97, 0xa3, 0x32, 0x87, 0x69, 0xee, + 0x2e, 0x15, 0x88, 0xc0, 0x0d, 0x0c, 0x9b, 0x21, 0x70, 0x8b, 0x42, 0x21, 0xa4, 0x9a, 0xee, 0xc1, + 0x90, 0x30, 0xd2, 0x39, 0x7e, 0x7a, 0x79, 0xfc, 0xfb, 0xec, 0x32, 0x4c, 0x9c, 0xca, 0x38, 0xbc, + 0x7d, 0x85, 0xb9, 0x9d, 0x6c, 0x32, 0xb5, 0x95, 0xd3, 0xd2, 0x36, 0xc2, 0x60, 0x0c, 0x1b, 0x9d, + 0x86, 0xf2, 0x96, 0x61, 0xd9, 0xba, 0x87, 0x0d, 0xdf, 0x75, 0xf8, 0x44, 0x81, 0x80, 0x34, 0x0a, + 0x51, 0x7f, 0xa4, 0xb0, 0x48, 0xed, 0x53, 0xae, 0xf1, 0x7e, 0x90, 0x81, 0xea, 0x9a, 0xe3, 0x63, + 0x2f, 0x38, 0xfe, 0x47, 0x13, 0xf4, 0x16, 0x94, 0xe9, 0xc4, 0x7c, 0xdd, 0x34, 0x02, 0x83, 0x5b, + 0xb3, 0x67, 0xa5, 0xa1, 0x99, 0x9b, 0x04, 0x6f, 0xd5, 0x08, 0x0c, 0x8d, 0x71, 0xc7, 0x27, 0xbf, + 0xd1, 0x09, 0x28, 0x6d, 0x1b, 0xfe, 0xb6, 0xfe, 0x10, 0xef, 0x31, 0x7f, 0xb1, 0xaa, 0x15, 0x09, + 0xe0, 0x5d, 0xbc, 0xe7, 0xa3, 0x67, 0xa0, 0xe8, 0xf4, 0x3a, 0x6c, 0x83, 0x15, 0x16, 0x95, 0xa5, + 0xaa, 0x56, 0x70, 0x7a, 0x1d, 0xb2, 0xbd, 0xd8, 0x85, 0x74, 0xb1, 0x91, 0x55, 0xff, 0x21, 0x03, + 0xb5, 0xbb, 0x3d, 0x72, 0x22, 0xa2, 0x11, 0xa6, 0x9e, 0x1d, 0x1c, 0x4e, 0x2a, 0xcf, 0x41, 0x96, + 0xf9, 0x16, 0xa4, 0x45, 0x43, 0x3a, 0x83, 0xb5, 0x55, 0x5f, 0x23, 0x48, 0x34, 0xba, 0xd2, 0x6b, + 0xb5, 0xb8, 0x9b, 0x96, 0xa5, 0x54, 0x97, 0x08, 0x84, 0x39, 0x69, 0x27, 0xa0, 0x84, 0x3d, 0x2f, + 0x72, 0xe2, 0xe8, 0x9c, 0xb0, 0xe7, 0xb1, 0x4a, 0x15, 0x2a, 0x46, 0xeb, 0xa1, 0xe3, 0xee, 0xda, + 0xd8, 0x6c, 0x63, 0x93, 0xae, 0x7f, 0x51, 0x8b, 0xc1, 0x98, 0x84, 0x10, 0x09, 0xd0, 0x5b, 0x4e, + 0x40, 0xcd, 0x7b, 0x96, 0x48, 0x08, 0x81, 0xdc, 0x70, 0x02, 0x52, 0x6d, 0x62, 0x1b, 0x07, 0x98, + 0x56, 0x17, 0x58, 0x35, 0x83, 0xf0, 0xea, 0x5e, 0x37, 0x6a, 0x5d, 0x64, 0xd5, 0x0c, 0x42, 0xaa, + 0x4f, 0x42, 0xa9, 0x7f, 0x03, 0x5e, 0xea, 0x5f, 0x61, 0xb2, 0x8b, 0xef, 0x9f, 0x28, 0x50, 0x5d, + 0xa5, 0x5d, 0x3d, 0x05, 0xd2, 0x87, 0x60, 0x12, 0x3f, 0xee, 0x7a, 0x7c, 0x0f, 0xd1, 0xdf, 0x43, + 0x05, 0x8a, 0x49, 0x4d, 0xa9, 0x91, 0x55, 0xff, 0x37, 0x0b, 0xd5, 0x0d, 0x6c, 0x78, 0xad, 0xed, + 0xa7, 0xe2, 0x7e, 0xa6, 0x0e, 0x59, 0xd3, 0xb7, 0xf9, 0x3c, 0xc9, 0x4f, 0x74, 0x1e, 0xa6, 0xbb, + 0xb6, 0xd1, 0xc2, 0xdb, 0xae, 0x6d, 0x62, 0x4f, 0x6f, 0x7b, 0x6e, 0x8f, 0x45, 0x10, 0x2b, 0x5a, + 0x5d, 0xa8, 0xb8, 0x45, 0xe0, 0xe8, 0x55, 0x28, 0x9a, 0xbe, 0xad, 0xd3, 0x83, 0x6d, 0x81, 0x2a, + 0x5d, 0xf9, 0xfc, 0x56, 0x7d, 0x9b, 0x9e, 0x6b, 0x0b, 0x26, 0xfb, 0x81, 0x9e, 0x83, 0xaa, 0xdb, + 0x0b, 0xba, 0xbd, 0x40, 0x67, 0x5b, 0xb6, 0x51, 0xa4, 0xe4, 0x55, 0x18, 0x90, 0xee, 0x68, 0x1f, + 0xdd, 0x84, 0xaa, 0x4f, 0x59, 0x19, 0xfa, 0xb4, 0xa5, 0x51, 0x7d, 0xab, 0x0a, 0x6b, 0xc7, 0x9d, + 0xda, 0x17, 0xa1, 0x1e, 0x78, 0xc6, 0x0e, 0xb6, 0x85, 0x08, 0x0d, 0x50, 0xf9, 0x9c, 0x62, 0xf0, + 0x7e, 0x78, 0x33, 0x25, 0x9e, 0x53, 0x4e, 0x8b, 0xe7, 0xa0, 0x1a, 0x64, 0x9c, 0x47, 0x34, 0x54, + 0x98, 0xd5, 0x32, 0xce, 0x23, 0xf5, 0x5d, 0x98, 0xbc, 0x6d, 0x05, 0x94, 0xb1, 0x64, 0xd7, 0x2b, + 0xf4, 0x44, 0x41, 0xf7, 0xf6, 0x33, 0x50, 0xf4, 0xdc, 0x5d, 0xa6, 0xce, 0x88, 0xbf, 0x55, 0xd1, + 0x0a, 0x9e, 0xbb, 0x4b, 0x75, 0x15, 0x4d, 0x32, 0x71, 0x3d, 0xcc, 0xbc, 0xc7, 0x8c, 0xc6, 0x4b, + 0xea, 0x9f, 0x28, 0x7d, 0x61, 0x22, 0x0a, 0xc8, 0x3f, 0x9c, 0x06, 0x7a, 0x0b, 0x0a, 0x1e, 0x6b, + 0x3f, 0x34, 0xc4, 0x2d, 0x8e, 0x44, 0xd5, 0x69, 0xd8, 0x6a, 0xf4, 0xf0, 0xcd, 0x37, 0x14, 0xa8, + 0xdc, 0xb4, 0x7b, 0xfe, 0x93, 0x10, 0x7e, 0x59, 0x00, 0x21, 0x2b, 0x0d, 0x20, 0xa8, 0xdf, 0xc9, + 0x40, 0x95, 0x93, 0x31, 0x8e, 0x3f, 0x91, 0x4a, 0xca, 0x06, 0x94, 0xc9, 0x90, 0xba, 0x8f, 0xdb, + 0xe1, 0xf5, 0x48, 0x79, 0x65, 0x45, 0xea, 0x3d, 0xc7, 0xc8, 0xa0, 0x59, 0x04, 0x1b, 0xb4, 0xd1, + 0x3b, 0x4e, 0xe0, 0xed, 0x69, 0xd0, 0x8a, 0x00, 0xcd, 0x8f, 0x60, 0x2a, 0x51, 0x4d, 0x84, 0xe8, + 0x21, 0xde, 0xe3, 0xe7, 0x10, 0xf2, 0x13, 0xbd, 0x2c, 0xe6, 0x7f, 0xa4, 0x19, 0xc4, 0x3b, 0xae, + 0xd3, 0xbe, 0xe6, 0x79, 0xc6, 0x1e, 0xcf, 0x0f, 0xb9, 0x9a, 0xf9, 0x8a, 0xa2, 0xfe, 0x6d, 0x06, + 0x2a, 0xef, 0xf5, 0xb0, 0xb7, 0x77, 0x94, 0x7a, 0x29, 0xd4, 0xab, 0x93, 0x82, 0x5e, 0x1d, 0x50, + 0x05, 0x39, 0x89, 0x2a, 0x90, 0x28, 0xb4, 0xbc, 0x54, 0xa1, 0xc9, 0xf6, 0x7a, 0xe1, 0x40, 0x7b, + 0xbd, 0x98, 0x1a, 0xbb, 0xfd, 0x63, 0x25, 0x62, 0xe1, 0x58, 0xbb, 0x31, 0xe6, 0xd9, 0x64, 0x0e, + 0xec, 0xd9, 0x8c, 0xbc, 0x1b, 0x7f, 0xa8, 0x40, 0xe9, 0x03, 0xdc, 0x0a, 0x5c, 0x8f, 0xe8, 0x1f, + 0x49, 0x33, 0x65, 0x04, 0x2f, 0x33, 0x93, 0xf4, 0x32, 0x2f, 0x43, 0xd1, 0x32, 0x75, 0x83, 0xc8, + 0x17, 0x1d, 0x77, 0x98, 0x53, 0x53, 0xb0, 0x4c, 0x2a, 0x88, 0xa3, 0xdf, 0xa7, 0x7f, 0x4f, 0x81, + 0x0a, 0xa3, 0xd9, 0x67, 0x2d, 0x5f, 0x17, 0x86, 0x53, 0x64, 0x42, 0xcf, 0x0b, 0xd1, 0x44, 0x6f, + 0x4f, 0xf4, 0x87, 0xbd, 0x06, 0x40, 0x98, 0xcc, 0x9b, 0xb3, 0x3d, 0xb3, 0x28, 0xa5, 0x96, 0x35, + 0xa7, 0x0c, 0xbf, 0x3d, 0xa1, 0x95, 0x48, 0x2b, 0xda, 0xc5, 0xf5, 0x02, 0xe4, 0x68, 0x6b, 0xf5, + 0x7f, 0x14, 0x98, 0xb9, 0x61, 0xd8, 0xad, 0x55, 0xcb, 0x0f, 0x0c, 0xa7, 0x35, 0x86, 0x1b, 0x73, + 0x15, 0x0a, 0x6e, 0x57, 0xb7, 0xf1, 0x56, 0xc0, 0x49, 0x3a, 0x33, 0x64, 0x46, 0x8c, 0x0d, 0x5a, + 0xde, 0xed, 0xde, 0xc1, 0x5b, 0x01, 0x7a, 0x03, 0x8a, 0x6e, 0x57, 0xf7, 0xac, 0xf6, 0x76, 0xc0, + 0xb9, 0x3f, 0x42, 0xe3, 0x82, 0xdb, 0xd5, 0x48, 0x0b, 0xe1, 0x9a, 0x62, 0xf2, 0x80, 0xd7, 0x14, + 0xea, 0x3f, 0x0f, 0x4c, 0x7f, 0x8c, 0x3d, 0x70, 0x15, 0x8a, 0x96, 0x13, 0xe8, 0xa6, 0xe5, 0x87, + 0x2c, 0x38, 0x25, 0x97, 0x21, 0x27, 0xa0, 0x33, 0xa0, 0x6b, 0xea, 0x04, 0x64, 0x6c, 0xf4, 0x36, + 0xc0, 0x96, 0xed, 0x1a, 0xbc, 0x35, 0xe3, 0xc1, 0x69, 0xf9, 0xf6, 0x21, 0x68, 0x61, 0xfb, 0x12, + 0x6d, 0x44, 0x7a, 0xe8, 0x2f, 0xe9, 0x3f, 0x29, 0x30, 0xb7, 0x8e, 0x3d, 0x96, 0x09, 0x14, 0xf0, + 0x1b, 0xc5, 0x35, 0x67, 0xcb, 0x8d, 0x5f, 0xea, 0x2a, 0x89, 0x4b, 0xdd, 0x9f, 0xcd, 0x45, 0x66, + 0xec, 0x10, 0xc2, 0x42, 0x0b, 0xe1, 0x21, 0x24, 0x0c, 0xa0, 0xb0, 0x43, 0x5c, 0x2d, 0x65, 0x99, + 0x38, 0xbd, 0xe2, 0x59, 0x56, 0xfd, 0x0d, 0x96, 0x3f, 0x21, 0x9d, 0xd4, 0xe1, 0x05, 0x76, 0x1e, + 0xb8, 0xa6, 0x4f, 0xe8, 0xfd, 0x2f, 0x41, 0x42, 0x77, 0xa4, 0x28, 0xa2, 0xef, 0x2b, 0xb0, 0x98, + 0x4e, 0xd5, 0x38, 0x26, 0xfa, 0x6d, 0xc8, 0x59, 0xce, 0x96, 0x1b, 0xde, 0x60, 0x9d, 0x93, 0xee, + 0x05, 0xf9, 0xb8, 0xac, 0xa1, 0xfa, 0xe3, 0x0c, 0xd4, 0xdf, 0x63, 0xf1, 0xf8, 0x2f, 0x7c, 0xf9, + 0x3b, 0xb8, 0xa3, 0xfb, 0xd6, 0x27, 0x38, 0x5c, 0xfe, 0x0e, 0xee, 0x6c, 0x58, 0x9f, 0xe0, 0x98, + 0x64, 0xe4, 0xe2, 0x92, 0x31, 0xfc, 0x82, 0x56, 0xbc, 0xa1, 0x2c, 0xc4, 0x6f, 0x28, 0xe7, 0x21, + 0xef, 0xb8, 0x26, 0x5e, 0x5b, 0xe5, 0x07, 0x37, 0x5e, 0xea, 0x8b, 0x5a, 0xe9, 0x60, 0xa2, 0x46, + 0x86, 0xa2, 0x5d, 0x98, 0x2c, 0x91, 0x8f, 0xd0, 0xc8, 0x8a, 0xea, 0xb7, 0x14, 0x68, 0xde, 0xc2, + 0x41, 0x92, 0xab, 0x47, 0x27, 0x7f, 0xdf, 0x56, 0xe0, 0x84, 0x94, 0xa0, 0x71, 0x44, 0xef, 0xf5, + 0xb8, 0xe8, 0xc9, 0x2f, 0x4f, 0x07, 0x86, 0xe4, 0x52, 0x77, 0x09, 0x2a, 0xab, 0xbd, 0x4e, 0x27, + 0x72, 0xc6, 0xce, 0x40, 0xc5, 0x63, 0x3f, 0xd9, 0x61, 0x8a, 0x59, 0xe6, 0x32, 0x87, 0x91, 0x23, + 0x93, 0x7a, 0x1e, 0xaa, 0xbc, 0x09, 0xa7, 0xba, 0x09, 0x45, 0x8f, 0xff, 0xe6, 0xf8, 0x51, 0x59, + 0x9d, 0x83, 0x19, 0x0d, 0xb7, 0x89, 0xd0, 0x7b, 0x77, 0x2c, 0xe7, 0x21, 0x1f, 0x46, 0xfd, 0xba, + 0x02, 0xb3, 0x71, 0x38, 0xef, 0xeb, 0x0a, 0x14, 0x0c, 0xd3, 0xf4, 0xb0, 0xef, 0x0f, 0x5d, 0x96, + 0x6b, 0x0c, 0x47, 0x0b, 0x91, 0x05, 0xce, 0x65, 0x46, 0xe6, 0x9c, 0xaa, 0xc3, 0xf4, 0x2d, 0x1c, + 0xdc, 0xc5, 0x81, 0x37, 0x56, 0x98, 0xbc, 0x41, 0x8e, 0x35, 0xb4, 0x31, 0x17, 0x8b, 0xb0, 0xa8, + 0x7e, 0xa6, 0x00, 0x12, 0x47, 0x18, 0x67, 0x99, 0x45, 0x2e, 0x67, 0xe2, 0x5c, 0x66, 0x89, 0x4a, + 0x9d, 0xae, 0xeb, 0x60, 0x27, 0x10, 0x1d, 0xb1, 0x6a, 0x04, 0x0d, 0x73, 0x37, 0xd0, 0x1d, 0xd7, + 0x30, 0xaf, 0x1b, 0xf6, 0x78, 0x8e, 0xc3, 0x29, 0x00, 0xdf, 0x6b, 0xe9, 0x7c, 0x1f, 0x67, 0xb8, + 0x5e, 0xf2, 0x5a, 0xf7, 0xd8, 0x56, 0x3e, 0x0d, 0x65, 0xd3, 0x0f, 0x78, 0x75, 0x18, 0xb5, 0x05, + 0xd3, 0x0f, 0x58, 0x3d, 0xcd, 0x0e, 0xf6, 0xb1, 0x61, 0x63, 0x53, 0x17, 0x82, 0x5e, 0x93, 0x14, + 0xad, 0xce, 0x2a, 0x36, 0x22, 0xb8, 0x64, 0x73, 0xe5, 0xa4, 0x9b, 0x6b, 0x0b, 0x16, 0xee, 0x1a, + 0x4e, 0xcf, 0xb0, 0x6f, 0xb8, 0x9d, 0xae, 0x11, 0x4b, 0x28, 0x4d, 0x2a, 0x4a, 0x45, 0xa2, 0x28, + 0x9f, 0x65, 0x99, 0x6f, 0xcc, 0x39, 0xa7, 0x73, 0x9a, 0xd4, 0x04, 0x08, 0xbb, 0x59, 0x29, 0x34, + 0x14, 0xd5, 0x87, 0xc6, 0xe0, 0x38, 0xe3, 0xac, 0x2c, 0xa5, 0x2e, 0xec, 0x4a, 0x54, 0xe3, 0x7d, + 0x98, 0xfa, 0x16, 0x3c, 0x43, 0xd3, 0x11, 0x43, 0x50, 0xec, 0xc2, 0x3d, 0xd9, 0x81, 0x22, 0xe9, + 0xe0, 0x57, 0x32, 0x54, 0x17, 0x0e, 0xf4, 0x30, 0x0e, 0xe1, 0x57, 0xe3, 0xf7, 0xdc, 0xcf, 0xa7, + 0xe4, 0x3c, 0xc7, 0x47, 0xe4, 0x5a, 0x7b, 0x09, 0xa6, 0xf0, 0x63, 0xdc, 0xea, 0x05, 0x96, 0xd3, + 0x5e, 0xb7, 0x0d, 0xe7, 0x9e, 0xcb, 0x6d, 0x53, 0x12, 0x8c, 0x9e, 0x87, 0x2a, 0x59, 0x06, 0xb7, + 0x17, 0x70, 0x3c, 0x66, 0xa4, 0xe2, 0x40, 0xd2, 0x1f, 0x99, 0xaf, 0x8d, 0x03, 0x6c, 0x72, 0x3c, + 0x66, 0xb1, 0x92, 0xe0, 0x01, 0x56, 0x12, 0xb0, 0x7f, 0x10, 0x56, 0xfe, 0x8b, 0x92, 0x60, 0x25, + 0xef, 0xe1, 0xa8, 0x58, 0x79, 0x1b, 0xa0, 0x83, 0xbd, 0x36, 0x5e, 0xa3, 0x56, 0x80, 0x5d, 0x02, + 0x2c, 0x49, 0xad, 0x40, 0xbf, 0x83, 0xbb, 0x61, 0x03, 0x4d, 0x68, 0xab, 0xde, 0x82, 0x19, 0x09, + 0x0a, 0x51, 0x70, 0xbe, 0xdb, 0xf3, 0x5a, 0x38, 0xbc, 0x47, 0x0a, 0x8b, 0xc4, 0x20, 0x06, 0x86, + 0xd7, 0xc6, 0x01, 0x17, 0x5a, 0x5e, 0x52, 0xaf, 0xd0, 0xd0, 0x10, 0xbd, 0x73, 0x88, 0x49, 0x6a, + 0x3c, 0xcc, 0xad, 0x0c, 0x84, 0xb9, 0xb7, 0x68, 0x1c, 0x46, 0x6c, 0x37, 0x66, 0x8a, 0xc2, 0x16, + 0xe9, 0x0a, 0x9b, 0xfc, 0x0d, 0x4c, 0x58, 0x54, 0x7f, 0xaa, 0x40, 0x75, 0xad, 0xd3, 0x75, 0xfb, + 0x21, 0x88, 0x91, 0x4f, 0xa5, 0x83, 0x37, 0xb7, 0x19, 0xd9, 0xcd, 0xed, 0x73, 0x50, 0x8d, 0xbf, + 0x96, 0x60, 0x57, 0x44, 0x95, 0x96, 0xf8, 0x4a, 0xe2, 0x04, 0x94, 0x3c, 0x77, 0x57, 0x27, 0x3a, + 0xd5, 0xe4, 0xc9, 0x10, 0x45, 0xcf, 0xdd, 0x25, 0x9a, 0xd6, 0x44, 0xb3, 0x90, 0xdb, 0xb2, 0xec, + 0x28, 0x8f, 0x87, 0x15, 0xd0, 0xeb, 0xe4, 0xcc, 0xc6, 0x82, 0xa5, 0xf9, 0x51, 0x8f, 0x4e, 0x61, + 0x0b, 0xf5, 0x43, 0xa8, 0x85, 0xb3, 0x1e, 0xf3, 0xf1, 0x4f, 0x60, 0xf8, 0x0f, 0xc3, 0x3c, 0x05, + 0x56, 0x50, 0xcf, 0xb3, 0x18, 0x1a, 0xed, 0x3f, 0xb6, 0xe8, 0x08, 0x26, 0x09, 0x06, 0xdf, 0x4b, + 0xf4, 0xb7, 0xfa, 0x8f, 0x19, 0x98, 0x4f, 0x62, 0x8f, 0x43, 0xd2, 0x95, 0xf8, 0xfe, 0x91, 0xbf, + 0xe5, 0x10, 0x47, 0xe3, 0x7b, 0x87, 0xaf, 0x40, 0xcb, 0xed, 0x39, 0x01, 0x57, 0x40, 0x64, 0x05, + 0x6e, 0x90, 0x32, 0x5a, 0x80, 0x82, 0x65, 0xea, 0x36, 0x39, 0xde, 0x31, 0xe3, 0x94, 0xb7, 0xcc, + 0x3b, 0xe4, 0xe8, 0xf7, 0x6a, 0xe8, 0x72, 0x8d, 0x9c, 0xdc, 0xc0, 0xf0, 0x51, 0x0d, 0x32, 0x96, + 0xc9, 0xe3, 0x1d, 0x19, 0xcb, 0x24, 0xc2, 0x44, 0xef, 0x05, 0x68, 0x22, 0x2e, 0xcf, 0xcc, 0x25, + 0x52, 0x50, 0x25, 0xd0, 0xf7, 0x42, 0x20, 0xf1, 0xca, 0x28, 0x1a, 0x8f, 0xce, 0x52, 0xcf, 0xb9, + 0xa8, 0x95, 0x09, 0x6c, 0x8d, 0x81, 0xd4, 0x06, 0xcc, 0x13, 0xd2, 0xd8, 0x14, 0x1f, 0x90, 0x05, + 0x09, 0x7d, 0xad, 0xef, 0x28, 0xb0, 0x30, 0x50, 0x35, 0x0e, 0xaf, 0xaf, 0x89, 0xcb, 0x5f, 0x5e, + 0x39, 0x2f, 0x55, 0x35, 0xf2, 0xc5, 0x0d, 0x65, 0xe5, 0xbb, 0xcc, 0x31, 0xd2, 0x58, 0xf2, 0xe5, + 0x13, 0x4e, 0xe5, 0x59, 0x82, 0xfa, 0xae, 0x15, 0x6c, 0xeb, 0xf4, 0x75, 0x10, 0xf5, 0x4a, 0x58, + 0x34, 0xbb, 0xa8, 0xd5, 0x08, 0x7c, 0x83, 0x80, 0x89, 0x67, 0xe2, 0xab, 0xdf, 0x54, 0x60, 0x26, + 0x46, 0xd6, 0x38, 0x6c, 0x7a, 0x83, 0x38, 0x6c, 0xac, 0x23, 0xce, 0xa9, 0x45, 0x29, 0xa7, 0xf8, + 0x68, 0x54, 0x19, 0x47, 0x2d, 0xd4, 0x7f, 0x55, 0xa0, 0x2c, 0xd4, 0x90, 0x93, 0x20, 0xaf, 0xeb, + 0x9f, 0x04, 0x23, 0xc0, 0x48, 0x6c, 0x78, 0x0e, 0xfa, 0x2a, 0x4a, 0x48, 0x66, 0x17, 0xb2, 0xe9, + 0x4c, 0x1f, 0xdd, 0x86, 0x1a, 0x63, 0x53, 0x44, 0xba, 0xf4, 0x82, 0x26, 0xca, 0x13, 0x34, 0x3c, + 0x93, 0x53, 0xa9, 0x55, 0x7d, 0xa1, 0xc4, 0x42, 0x9b, 0xae, 0x89, 0xe9, 0x48, 0xb9, 0x81, 0x73, + 0x59, 0x45, 0x6c, 0x4a, 0x7c, 0x5b, 0x1b, 0x1b, 0x26, 0xf6, 0xa2, 0xb9, 0x45, 0x65, 0xe2, 0x4c, + 0xb2, 0xdf, 0x3a, 0xf1, 0xf5, 0xb9, 0xb2, 0x05, 0x06, 0x22, 0xc7, 0x00, 0xf4, 0x25, 0x98, 0x32, + 0x3b, 0xb1, 0xa7, 0x69, 0xa1, 0xf7, 0x6b, 0x76, 0x84, 0x37, 0x69, 0x31, 0x82, 0x26, 0xe3, 0x04, + 0xfd, 0xb7, 0x12, 0x3d, 0xf6, 0xf5, 0xb0, 0x89, 0x9d, 0xc0, 0x32, 0xec, 0xc3, 0xcb, 0x64, 0x13, + 0x8a, 0x3d, 0x1f, 0x7b, 0x82, 0x6d, 0x88, 0xca, 0xa4, 0xae, 0x6b, 0xf8, 0xfe, 0xae, 0xeb, 0x99, + 0x9c, 0xca, 0xa8, 0x3c, 0x24, 0x35, 0x91, 0x3d, 0x10, 0x95, 0xa7, 0x26, 0x5e, 0x81, 0x85, 0x8e, + 0x6b, 0x5a, 0x5b, 0x96, 0x2c, 0xa3, 0x91, 0x34, 0x9b, 0x0b, 0xab, 0x63, 0xed, 0xd4, 0xef, 0x67, + 0x60, 0xe1, 0xfd, 0xae, 0xf9, 0x05, 0xcc, 0x79, 0x11, 0xca, 0xae, 0x6d, 0xae, 0xc7, 0xa7, 0x2d, + 0x82, 0x08, 0x86, 0x83, 0x77, 0x23, 0x0c, 0x76, 0x2b, 0x2f, 0x82, 0x86, 0xa6, 0x6d, 0x1e, 0x8a, + 0x37, 0xf9, 0x61, 0xbc, 0x69, 0xc3, 0x02, 0x0b, 0x11, 0x3f, 0x61, 0xd6, 0xa8, 0x1f, 0xc3, 0x1c, + 0x51, 0xcd, 0x64, 0x98, 0xf7, 0x7d, 0xec, 0x8d, 0xa9, 0x71, 0x4e, 0x42, 0x29, 0xec, 0x39, 0xcc, + 0xa8, 0xed, 0x03, 0xd4, 0xdb, 0x30, 0x9b, 0x18, 0xeb, 0x90, 0x33, 0x52, 0x17, 0x01, 0x34, 0xd7, + 0xc6, 0xef, 0x38, 0x81, 0x15, 0xec, 0x11, 0xf3, 0x2e, 0xb8, 0x4b, 0xf4, 0x37, 0xc1, 0x20, 0x63, + 0x0c, 0xc1, 0xf8, 0x45, 0x98, 0x66, 0x3b, 0x8e, 0xf4, 0x74, 0x78, 0xe6, 0xbe, 0x0a, 0x79, 0x4c, + 0x07, 0xe1, 0xe7, 0xfe, 0xd3, 0x72, 0x15, 0x1b, 0x51, 0xab, 0x71, 0x74, 0xf5, 0x17, 0x60, 0x6a, + 0xd5, 0x73, 0xbb, 0xe3, 0x8d, 0x4e, 0xbd, 0x07, 0x1b, 0x8b, 0x6e, 0x60, 0x91, 0x00, 0xe8, 0x79, + 0xf4, 0xef, 0x14, 0x98, 0xbf, 0xdf, 0xc5, 0x9e, 0x11, 0x60, 0xc2, 0x8b, 0xf1, 0x46, 0x1a, 0xb6, + 0xbf, 0x62, 0x54, 0x64, 0xe3, 0x54, 0xa0, 0x37, 0x62, 0x2f, 0xb6, 0xe4, 0xc7, 0x82, 0x04, 0x95, + 0x42, 0xe6, 0xf7, 0x1f, 0x2a, 0x30, 0xbd, 0x81, 0x89, 0x0d, 0x19, 0x8f, 0xfc, 0xcb, 0x30, 0x49, + 0x28, 0x1a, 0x75, 0x91, 0x28, 0x32, 0x3a, 0x07, 0xd3, 0x96, 0xd3, 0xb2, 0x7b, 0x26, 0xd6, 0xc9, + 0x5c, 0x75, 0xe2, 0x42, 0x71, 0xc3, 0x3d, 0xc5, 0x2b, 0x08, 0xc9, 0xc4, 0x3c, 0xaa, 0x8f, 0x99, + 0x48, 0x46, 0xf9, 0x31, 0x6c, 0x38, 0xe5, 0x20, 0xc3, 0xbd, 0x02, 0x39, 0x32, 0x4c, 0x68, 0xac, + 0xe5, 0xad, 0xfa, 0x52, 0xad, 0x31, 0x6c, 0xf5, 0x1b, 0x0a, 0x20, 0x91, 0x45, 0xe3, 0x6c, 0xe0, + 0xd7, 0xc4, 0x00, 0x79, 0x76, 0x28, 0xe9, 0x6c, 0xa6, 0x51, 0x68, 0x5c, 0x58, 0x29, 0xba, 0x8c, + 0xe3, 0xac, 0x14, 0x99, 0xd7, 0xd0, 0x95, 0x12, 0x98, 0x40, 0x91, 0xc5, 0x95, 0xa2, 0x92, 0x28, + 0x59, 0x29, 0x42, 0x73, 0xb8, 0x52, 0x8c, 0xc2, 0x70, 0xa5, 0xe8, 0x70, 0xca, 0x41, 0x86, 0x7b, + 0x05, 0x72, 0x64, 0x98, 0xfd, 0x99, 0x14, 0xae, 0x14, 0xc5, 0x16, 0x56, 0x8a, 0x13, 0xf0, 0xe4, + 0x57, 0xaa, 0x3f, 0xd3, 0xfe, 0x4a, 0xa9, 0x50, 0xb9, 0xbf, 0xf9, 0x31, 0x6e, 0x05, 0x43, 0xb4, + 0xe3, 0x59, 0x98, 0x5a, 0xf7, 0xac, 0x1d, 0xcb, 0xc6, 0xed, 0x61, 0x6a, 0xf6, 0x9b, 0x0a, 0x54, + 0x6f, 0x79, 0x86, 0x13, 0xb8, 0xa1, 0xaa, 0x3d, 0x14, 0x3f, 0xaf, 0x43, 0xa9, 0x1b, 0x8e, 0xc6, + 0x17, 0xfe, 0x79, 0x79, 0x00, 0x23, 0x4e, 0x93, 0xd6, 0x6f, 0xa6, 0x7e, 0x00, 0xb3, 0x94, 0x92, + 0x24, 0xd9, 0x6f, 0x42, 0x91, 0x6a, 0x5c, 0x8b, 0x5f, 0x1e, 0x94, 0x57, 0x54, 0xf9, 0x79, 0x41, + 0x9c, 0x86, 0x16, 0xb5, 0x51, 0xff, 0x5d, 0x81, 0x32, 0xad, 0xeb, 0x4f, 0xf0, 0xe0, 0x5b, 0xfb, + 0x35, 0xc8, 0xbb, 0x94, 0xe5, 0x43, 0xe3, 0x9c, 0xe2, 0xaa, 0x68, 0xbc, 0x01, 0x71, 0x3f, 0xd9, + 0x2f, 0x51, 0xbd, 0x02, 0x03, 0x71, 0x05, 0x5b, 0x68, 0x33, 0xda, 0xa9, 0x8e, 0x1d, 0x6d, 0x7e, + 0x61, 0x13, 0xf5, 0xd3, 0x48, 0x26, 0x29, 0xc2, 0xe1, 0xf7, 0xed, 0x57, 0x12, 0x86, 0x70, 0x31, + 0x9d, 0x8a, 0x84, 0x25, 0x24, 0x87, 0x9e, 0x18, 0x09, 0x63, 0x1e, 0x7a, 0xa2, 0xe5, 0x1e, 0x76, + 0xe8, 0x11, 0x09, 0xe9, 0x2f, 0xf6, 0x8f, 0x14, 0x58, 0xe0, 0xc6, 0x28, 0x92, 0xa3, 0x23, 0x60, + 0x09, 0xfa, 0x2a, 0x37, 0x9a, 0x59, 0x6a, 0x34, 0x5f, 0x1c, 0x66, 0x34, 0x23, 0x3a, 0x05, 0xab, + 0x79, 0x16, 0x4a, 0x77, 0x29, 0xd2, 0x3b, 0x8f, 0x03, 0xd4, 0x80, 0xc2, 0x0e, 0xf6, 0x7c, 0xcb, + 0x75, 0xf8, 0xd6, 0x0d, 0x8b, 0xe7, 0xce, 0x40, 0x31, 0x7c, 0x68, 0x85, 0x0a, 0x90, 0xbd, 0x66, + 0xdb, 0xf5, 0x09, 0x54, 0x81, 0xe2, 0x1a, 0x7f, 0x4d, 0x54, 0x57, 0xce, 0xbd, 0x0d, 0x33, 0x12, + 0xe3, 0x8c, 0xa6, 0xa1, 0x7a, 0xcd, 0xa4, 0x5e, 0xdc, 0x03, 0x97, 0x00, 0xeb, 0x13, 0x68, 0x1e, + 0x90, 0x86, 0x3b, 0xee, 0x0e, 0x45, 0xbc, 0xe9, 0xb9, 0x1d, 0x0a, 0x57, 0xce, 0x5d, 0x80, 0x59, + 0x19, 0xa5, 0xa8, 0x04, 0x39, 0x3a, 0xf3, 0xfa, 0x04, 0x02, 0xc8, 0x6b, 0x78, 0xc7, 0x7d, 0x88, + 0xeb, 0xca, 0xca, 0x5f, 0x9c, 0x83, 0x2a, 0xa3, 0x9d, 0x3f, 0x0b, 0x46, 0x3a, 0xd4, 0x93, 0xdf, + 0x41, 0x42, 0x5f, 0x96, 0xdf, 0x2e, 0xca, 0x3f, 0x97, 0xd4, 0x1c, 0x26, 0x38, 0xea, 0x04, 0xfa, + 0x10, 0x6a, 0xf1, 0x2f, 0x07, 0x21, 0x79, 0xf4, 0x54, 0xfa, 0x79, 0xa1, 0xfd, 0x3a, 0xd7, 0xa1, + 0x1a, 0xfb, 0xe8, 0x0f, 0x92, 0x2f, 0xa6, 0xec, 0xc3, 0x40, 0x4d, 0xb9, 0x96, 0x10, 0x3f, 0xcc, + 0xc3, 0xa8, 0x8f, 0x7f, 0x85, 0x23, 0x85, 0x7a, 0xe9, 0xa7, 0x3a, 0xf6, 0xa3, 0xde, 0x80, 0xe9, + 0x81, 0x8f, 0x64, 0xa0, 0x0b, 0x29, 0xb7, 0x08, 0xf2, 0x8f, 0x69, 0xec, 0x37, 0xc4, 0x2e, 0xa0, + 0xc1, 0x0f, 0xd9, 0xa0, 0x65, 0xf9, 0x0a, 0xa4, 0x7d, 0xda, 0xa7, 0x79, 0x71, 0x64, 0xfc, 0x88, + 0x71, 0xbf, 0xac, 0xc0, 0x42, 0xca, 0x17, 0x16, 0xd0, 0xe5, 0xb4, 0x2b, 0xa5, 0x21, 0x9f, 0x89, + 0x68, 0xbe, 0x7c, 0xb0, 0x46, 0x11, 0x21, 0x0e, 0x4c, 0x25, 0x3e, 0x30, 0x80, 0xce, 0xa7, 0xbe, + 0x8a, 0x1c, 0xfc, 0xfa, 0x42, 0xf3, 0xcb, 0xa3, 0x21, 0x47, 0xe3, 0x7d, 0x04, 0x53, 0x89, 0xd7, + 0xf5, 0x29, 0xe3, 0xc9, 0xdf, 0xe0, 0xef, 0xb7, 0xa0, 0x5f, 0x83, 0x6a, 0xec, 0x19, 0x7c, 0x8a, + 0xc4, 0xcb, 0x9e, 0xca, 0xef, 0xd7, 0xf5, 0x47, 0x50, 0x11, 0x5f, 0xab, 0xa3, 0xa5, 0xb4, 0xbd, + 0x34, 0xd0, 0xf1, 0x41, 0xb6, 0x52, 0xff, 0x95, 0xe9, 0x90, 0xad, 0x34, 0xf0, 0x30, 0x77, 0xf4, + 0xad, 0x24, 0xf4, 0x3f, 0x74, 0x2b, 0x1d, 0x78, 0x88, 0xaf, 0x2b, 0xf4, 0x4e, 0x5b, 0xf2, 0x8a, + 0x19, 0xad, 0xa4, 0xc9, 0x66, 0xfa, 0x7b, 0xed, 0xe6, 0xe5, 0x03, 0xb5, 0x89, 0xb8, 0xf8, 0x10, + 0x6a, 0xf1, 0xb7, 0xba, 0x29, 0x5c, 0x94, 0x3e, 0x6f, 0x6e, 0x9e, 0x1f, 0x09, 0x37, 0x1a, 0xec, + 0x7d, 0x28, 0x0b, 0x9f, 0x36, 0x44, 0x2f, 0x0c, 0x91, 0x63, 0xf1, 0x3b, 0x7f, 0xfb, 0x71, 0xf2, + 0x3d, 0x28, 0x45, 0x5f, 0x24, 0x44, 0x67, 0x53, 0xe5, 0xf7, 0x20, 0x5d, 0x6e, 0x00, 0xf4, 0x3f, + 0x37, 0x88, 0xbe, 0x24, 0xed, 0x73, 0xe0, 0x7b, 0x84, 0xfb, 0x75, 0x1a, 0x4d, 0x9f, 0xbd, 0x7c, + 0x18, 0x36, 0x7d, 0xf1, 0xcd, 0xce, 0x7e, 0xdd, 0x6e, 0x43, 0x35, 0xf6, 0xd2, 0x2e, 0x6d, 0x0b, + 0x4b, 0x1e, 0x40, 0x36, 0xcf, 0x8d, 0x82, 0x1a, 0xad, 0xdf, 0x36, 0x54, 0x63, 0xef, 0x9e, 0x52, + 0x46, 0x92, 0x3d, 0xf3, 0x4a, 0x19, 0x49, 0xfa, 0x8c, 0x4a, 0x9d, 0x40, 0x9f, 0x0a, 0x4f, 0xac, + 0x62, 0xcf, 0xd8, 0xd0, 0xa5, 0xa1, 0xfd, 0xc8, 0x5e, 0xf1, 0x35, 0x57, 0x0e, 0xd2, 0x24, 0x22, + 0x81, 0x4b, 0x15, 0x63, 0x69, 0xba, 0x54, 0x1d, 0x64, 0xa5, 0x36, 0x20, 0xcf, 0x5e, 0x32, 0x21, + 0x35, 0xe5, 0xcd, 0xa2, 0xf0, 0xcc, 0xa9, 0xf9, 0x9c, 0x14, 0x27, 0xfe, 0xb6, 0x87, 0x75, 0xca, + 0x6e, 0x1f, 0x53, 0x3a, 0x8d, 0xbd, 0x5e, 0x19, 0xb5, 0x53, 0x0d, 0xf2, 0x2c, 0xaf, 0x3e, 0xa5, + 0xd3, 0xd8, 0x5b, 0x91, 0xe6, 0x70, 0x1c, 0x76, 0x8e, 0x9d, 0x40, 0xeb, 0x90, 0xa3, 0xa1, 0x5a, + 0x74, 0x66, 0x58, 0xca, 0xf9, 0xb0, 0x1e, 0x63, 0x59, 0xe9, 0xea, 0x04, 0xba, 0x0f, 0x39, 0x1a, + 0xf5, 0x4a, 0xe9, 0x51, 0xcc, 0x1b, 0x6f, 0x0e, 0x45, 0x09, 0x49, 0x34, 0xa1, 0x22, 0x26, 0x8b, + 0xa6, 0x98, 0x2c, 0x49, 0x3a, 0x6d, 0x73, 0x14, 0xcc, 0x70, 0x14, 0xb6, 0x8d, 0xfa, 0x61, 0xeb, + 0xf4, 0x6d, 0x34, 0x10, 0x12, 0x4f, 0xdf, 0x46, 0x83, 0x51, 0x70, 0x75, 0x02, 0xfd, 0xaa, 0x02, + 0x8d, 0xb4, 0x0c, 0x46, 0x94, 0xea, 0x01, 0x0d, 0x4b, 0xc3, 0x6c, 0xbe, 0x72, 0xc0, 0x56, 0x11, + 0x2d, 0x9f, 0xd0, 0x60, 0xd9, 0x40, 0xce, 0xe2, 0xc5, 0xb4, 0xfe, 0x52, 0xf2, 0xf0, 0x9a, 0x2f, + 0x8d, 0xde, 0x20, 0x1a, 0x7b, 0x13, 0xca, 0x42, 0xa0, 0x2e, 0x45, 0xf3, 0x0e, 0x46, 0x18, 0x53, + 0x56, 0x55, 0x12, 0xf3, 0x63, 0xe2, 0x4d, 0x13, 0xdd, 0x52, 0x84, 0x51, 0xcc, 0x9b, 0x4b, 0x11, + 0xef, 0x58, 0x9e, 0x9c, 0x3a, 0x81, 0x30, 0x54, 0xc4, 0xac, 0xb7, 0x14, 0x69, 0x94, 0x24, 0xcc, + 0x35, 0x5f, 0x1c, 0x01, 0x33, 0x1a, 0x46, 0x07, 0xe8, 0x67, 0x9d, 0xa5, 0xd8, 0xba, 0x81, 0xc4, + 0xb7, 0xe6, 0x0b, 0xfb, 0xe2, 0x89, 0x66, 0x5f, 0xc8, 0x23, 0x4b, 0xe1, 0xfe, 0x60, 0xa6, 0xd9, + 0x08, 0x67, 0x91, 0xc1, 0x14, 0xa5, 0x94, 0xb3, 0x48, 0x6a, 0x36, 0x54, 0xf3, 0xe2, 0xc8, 0xf8, + 0xd1, 0x7c, 0x1e, 0x41, 0x3d, 0x99, 0xd2, 0x95, 0x72, 0xc6, 0x4d, 0xc9, 0x30, 0x6b, 0x5e, 0x18, + 0x11, 0x5b, 0xb4, 0x87, 0x27, 0x06, 0x69, 0xfa, 0x39, 0x2b, 0xd8, 0xa6, 0xd9, 0x44, 0xa3, 0xcc, + 0x5a, 0x4c, 0x5c, 0x1a, 0x65, 0xd6, 0xb1, 0x34, 0x25, 0x6e, 0xbc, 0x68, 0x88, 0x3e, 0xcd, 0x78, + 0x89, 0x09, 0x32, 0x29, 0x76, 0x26, 0x9e, 0x4e, 0xc2, 0xdc, 0xcf, 0x78, 0xe8, 0x1f, 0x9d, 0x1b, + 0x29, 0x3f, 0x60, 0x98, 0xfb, 0x29, 0xcf, 0x25, 0x60, 0x47, 0xb7, 0x44, 0x66, 0x43, 0xca, 0x51, + 0x4a, 0x9e, 0x1a, 0x91, 0x72, 0x74, 0x4b, 0x49, 0x96, 0xa0, 0x1b, 0xab, 0x9e, 0x0c, 0x13, 0x0f, + 0xbf, 0x0b, 0x49, 0x86, 0x0f, 0xf7, 0xbf, 0xae, 0xa8, 0x27, 0x63, 0xb2, 0x29, 0x03, 0xa4, 0x84, + 0x6e, 0x47, 0x18, 0x20, 0x19, 0xd9, 0x4c, 0x19, 0x20, 0x25, 0x00, 0x3a, 0x82, 0xef, 0x1a, 0x8b, + 0x32, 0xa6, 0x98, 0x42, 0x59, 0x24, 0x32, 0xc5, 0x14, 0x4a, 0x03, 0xa4, 0xcc, 0xa3, 0xef, 0x47, + 0x10, 0x53, 0xb4, 0xdc, 0x40, 0x88, 0x71, 0x3f, 0xf2, 0xef, 0x43, 0x31, 0x0c, 0x0b, 0xa2, 0xe7, + 0x53, 0x5d, 0xc4, 0x03, 0x74, 0xf8, 0x11, 0x4c, 0x25, 0x6e, 0xf0, 0x52, 0x44, 0x54, 0x1e, 0x2a, + 0xdc, 0x7f, 0x3d, 0xa1, 0x1f, 0x7c, 0x4a, 0x61, 0xc2, 0x40, 0x00, 0x2f, 0x45, 0xd5, 0x0f, 0x46, + 0xb1, 0xc4, 0x01, 0x08, 0x61, 0x43, 0x07, 0x10, 0xe2, 0x4e, 0x43, 0x07, 0x10, 0x83, 0x2f, 0x4c, + 0x22, 0x93, 0x17, 0x94, 0x29, 0x12, 0x99, 0x72, 0x33, 0xbc, 0x1f, 0x8b, 0x36, 0xa1, 0x2c, 0x5c, + 0x6f, 0xa3, 0x61, 0xa4, 0x89, 0x77, 0xf0, 0x29, 0xae, 0x82, 0xe4, 0xa6, 0x5c, 0x9d, 0x58, 0xe9, + 0x41, 0x65, 0xdd, 0x73, 0x1f, 0x87, 0xdf, 0x52, 0xfc, 0x82, 0x0c, 0xfd, 0xd5, 0x16, 0xd4, 0x18, + 0x82, 0x8e, 0x1f, 0x07, 0xba, 0xbb, 0xf9, 0x31, 0x3a, 0xb9, 0xcc, 0xfe, 0x1f, 0xc1, 0x72, 0xf8, + 0xff, 0x08, 0x96, 0x6f, 0x5a, 0x36, 0xbe, 0xcf, 0x33, 0x06, 0xff, 0xb3, 0x30, 0xe4, 0xe1, 0x5a, + 0x74, 0x65, 0xad, 0xf1, 0x7f, 0x89, 0xf0, 0xce, 0xe3, 0xe0, 0xfe, 0xe6, 0xc7, 0xd7, 0x8d, 0xcf, + 0xdf, 0x2c, 0x40, 0x6e, 0x65, 0xf9, 0xd2, 0xf2, 0x4b, 0x50, 0xb3, 0x22, 0xf4, 0xb6, 0xd7, 0x6d, + 0x5d, 0x2f, 0xb3, 0x46, 0xeb, 0xa4, 0x9f, 0x75, 0xe5, 0xe7, 0x2f, 0xb7, 0xad, 0x60, 0xbb, 0xb7, + 0x49, 0x96, 0xe0, 0x22, 0x43, 0xbb, 0x60, 0xb9, 0xfc, 0xd7, 0x45, 0xcb, 0x09, 0xb0, 0xe7, 0x18, + 0x36, 0xfb, 0x57, 0x09, 0x1c, 0xda, 0xdd, 0xfc, 0x5d, 0x45, 0xd9, 0xcc, 0x53, 0xd0, 0xe5, 0xff, + 0x0f, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xa2, 0xfe, 0xb7, 0x8c, 0x61, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -7657,7 +7440,6 @@ type MilvusServiceClient interface { OperateUserRole(ctx context.Context, in *OperateUserRoleRequest, opts ...grpc.CallOption) (*commonpb.Status, error) SelectRole(ctx context.Context, in *SelectRoleRequest, opts ...grpc.CallOption) (*SelectRoleResponse, error) SelectUser(ctx context.Context, in *SelectUserRequest, opts ...grpc.CallOption) (*SelectUserResponse, error) - SelectResource(ctx context.Context, in *SelectResourceRequest, opts ...grpc.CallOption) (*SelectResourceResponse, error) OperatePrivilege(ctx context.Context, in *OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error) SelectGrant(ctx context.Context, in *SelectGrantRequest, opts ...grpc.CallOption) (*SelectGrantResponse, error) } @@ -8138,15 +7920,6 @@ func (c *milvusServiceClient) SelectUser(ctx context.Context, in *SelectUserRequ return out, nil } -func (c *milvusServiceClient) SelectResource(ctx context.Context, in *SelectResourceRequest, opts ...grpc.CallOption) (*SelectResourceResponse, error) { - out := new(SelectResourceResponse) - err := c.cc.Invoke(ctx, "/milvus.proto.milvus.MilvusService/SelectResource", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *milvusServiceClient) OperatePrivilege(ctx context.Context, in *OperatePrivilegeRequest, opts ...grpc.CallOption) (*commonpb.Status, error) { out := new(commonpb.Status) err := c.cc.Invoke(ctx, "/milvus.proto.milvus.MilvusService/OperatePrivilege", in, out, opts...) @@ -8224,7 +7997,6 @@ type MilvusServiceServer interface { OperateUserRole(context.Context, *OperateUserRoleRequest) (*commonpb.Status, error) SelectRole(context.Context, *SelectRoleRequest) (*SelectRoleResponse, error) SelectUser(context.Context, *SelectUserRequest) (*SelectUserResponse, error) - SelectResource(context.Context, *SelectResourceRequest) (*SelectResourceResponse, error) OperatePrivilege(context.Context, *OperatePrivilegeRequest) (*commonpb.Status, error) SelectGrant(context.Context, *SelectGrantRequest) (*SelectGrantResponse, error) } @@ -8389,9 +8161,6 @@ func (*UnimplementedMilvusServiceServer) SelectRole(ctx context.Context, req *Se func (*UnimplementedMilvusServiceServer) SelectUser(ctx context.Context, req *SelectUserRequest) (*SelectUserResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SelectUser not implemented") } -func (*UnimplementedMilvusServiceServer) SelectResource(ctx context.Context, req *SelectResourceRequest) (*SelectResourceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SelectResource not implemented") -} func (*UnimplementedMilvusServiceServer) OperatePrivilege(ctx context.Context, req *OperatePrivilegeRequest) (*commonpb.Status, error) { return nil, status.Errorf(codes.Unimplemented, "method OperatePrivilege not implemented") } @@ -9339,24 +9108,6 @@ func _MilvusService_SelectUser_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _MilvusService_SelectResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SelectResourceRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MilvusServiceServer).SelectResource(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/milvus.proto.milvus.MilvusService/SelectResource", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MilvusServiceServer).SelectResource(ctx, req.(*SelectResourceRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _MilvusService_OperatePrivilege_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(OperatePrivilegeRequest) if err := dec(in); err != nil { @@ -9605,10 +9356,6 @@ var _MilvusService_serviceDesc = grpc.ServiceDesc{ MethodName: "SelectUser", Handler: _MilvusService_SelectUser_Handler, }, - { - MethodName: "SelectResource", - Handler: _MilvusService_SelectResource_Handler, - }, { MethodName: "OperatePrivilege", Handler: _MilvusService_OperatePrivilege_Handler, diff --git a/internal/proto/root_coord.proto b/internal/proto/root_coord.proto index bdcda9e1aa..cfd705f677 100644 --- a/internal/proto/root_coord.proto +++ b/internal/proto/root_coord.proto @@ -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) {} diff --git a/internal/proto/rootcoordpb/root_coord.pb.go b/internal/proto/rootcoordpb/root_coord.pb.go index ec1e377fad..b48bbecbd1 100644 --- a/internal/proto/rootcoordpb/root_coord.pb.go +++ b/internal/proto/rootcoordpb/root_coord.pb.go @@ -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, diff --git a/internal/proxy/authentication_interceptor_test.go b/internal/proxy/authentication_interceptor_test.go index 0105633846..05c5475758 100644 --- a/internal/proxy/authentication_interceptor_test.go +++ b/internal/proxy/authentication_interceptor_test.go @@ -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") diff --git a/internal/proxy/impl.go b/internal/proxy/impl.go index 609a759a25..95a40adef6 100644 --- a/internal/proxy/impl.go +++ b/internal/proxy/impl.go @@ -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 } diff --git a/internal/proxy/meta_cache.go b/internal/proxy/meta_cache.go index 0c6065b3f5..e3dab22a39 100644 --- a/internal/proxy/meta_cache.go +++ b/internal/proxy/meta_cache.go @@ -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 +} diff --git a/internal/proxy/meta_cache_test.go b/internal/proxy/meta_cache_test.go index c49f664620..50a9c02d77 100644 --- a/internal/proxy/meta_cache_test.go +++ b/internal/proxy/meta_cache_test.go @@ -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") diff --git a/internal/proxy/mock_cache_test.go b/internal/proxy/mock_cache_test.go index e8adfce412..76b4e8cb4d 100644 --- a/internal/proxy/mock_cache_test.go +++ b/internal/proxy/mock_cache_test.go @@ -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 } diff --git a/internal/proxy/privilege_interceptor.go b/internal/proxy/privilege_interceptor.go new file mode 100644 index 0000000000..078bb2d8b3 --- /dev/null +++ b/internal/proxy/privilege_interceptor.go @@ -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" +} diff --git a/internal/proxy/privilege_interceptor_test.go b/internal/proxy/privilege_interceptor_test.go new file mode 100644 index 0000000000..f506a0c874 --- /dev/null +++ b/internal/proxy/privilege_interceptor_test.go @@ -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) + + }) + +} diff --git a/internal/proxy/proxy.go b/internal/proxy/proxy.go index 0c41249872..433128ce40 100644 --- a/internal/proxy/proxy.go +++ b/internal/proxy/proxy.go @@ -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 } diff --git a/internal/proxy/proxy_test.go b/internal/proxy/proxy_test.go index 2602e312e9..6a3df36d15 100644 --- a/internal/proxy/proxy_test.go +++ b/internal/proxy/proxy_test.go @@ -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{} diff --git a/internal/proxy/rootcoord_mock_test.go b/internal/proxy/rootcoord_mock_test.go index 30e8b49d37..bd18f5fee9 100644 --- a/internal/proxy/rootcoord_mock_test.go +++ b/internal/proxy/rootcoord_mock_test.go @@ -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{} } diff --git a/internal/proxy/task_index_test.go b/internal/proxy/task_index_test.go index 9865b43f2d..0d970643f7 100644 --- a/internal/proxy/task_index_test.go +++ b/internal/proxy/task_index_test.go @@ -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{ diff --git a/internal/proxy/task_query_test.go b/internal/proxy/task_query_test.go index 6d2499595a..edbe0259bc 100644 --- a/internal/proxy/task_query_test.go +++ b/internal/proxy/task_query_test.go @@ -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{ diff --git a/internal/proxy/task_search_test.go b/internal/proxy/task_search_test.go index 9c43280689..3ae8435fec 100644 --- a/internal/proxy/task_search_test.go +++ b/internal/proxy/task_search_test.go @@ -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{ diff --git a/internal/proxy/task_test.go b/internal/proxy/task_test.go index ea45813755..a01b810bea 100644 --- a/internal/proxy/task_test.go +++ b/internal/proxy/task_test.go @@ -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) diff --git a/internal/proxy/util.go b/internal/proxy/util.go index 45fc9bef4e..86255cbc58 100644 --- a/internal/proxy/util.go +++ b/internal/proxy/util.go @@ -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") +} diff --git a/internal/proxy/util_test.go b/internal/proxy/util_test.go index d0e61ea5bf..1d1b3029dd 100644 --- a/internal/proxy/util_test.go +++ b/internal/proxy/util_test.go @@ -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) +} diff --git a/internal/rootcoord/meta_table.go b/internal/rootcoord/meta_table.go index 131b581887..a7fec24a58 100644 --- a/internal/rootcoord/meta_table.go +++ b/internal/rootcoord/meta_table.go @@ -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) +} diff --git a/internal/rootcoord/meta_table_test.go b/internal/rootcoord/meta_table_test.go index 9f1d8e1963..d37a2bbd26 100644 --- a/internal/rootcoord/meta_table_test.go +++ b/internal/rootcoord/meta_table_test.go @@ -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) diff --git a/internal/rootcoord/proxy_client_manager.go b/internal/rootcoord/proxy_client_manager.go index 5d6bd9ff4b..e363ae9916 100644 --- a/internal/rootcoord/proxy_client_manager.go +++ b/internal/rootcoord/proxy_client_manager.go @@ -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() +} diff --git a/internal/rootcoord/proxy_client_manager_test.go b/internal/rootcoord/proxy_client_manager_test.go index 469f67437c..3b6c6dc9c5 100644 --- a/internal/rootcoord/proxy_client_manager_test.go +++ b/internal/rootcoord/proxy_client_manager_test.go @@ -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) + +} diff --git a/internal/rootcoord/root_coord.go b/internal/rootcoord/root_coord.go index ece8b8dd62..3a8e85cef1 100644 --- a/internal/rootcoord/root_coord.go +++ b/internal/rootcoord/root_coord.go @@ -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 +} diff --git a/internal/rootcoord/root_coord_test.go b/internal/rootcoord/root_coord_test.go index 947836762d..8567cf6d40 100644 --- a/internal/rootcoord/root_coord_test.go +++ b/internal/rootcoord/root_coord_test.go @@ -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) + } +} diff --git a/internal/rootcoord/util.go b/internal/rootcoord/util.go index 264db86d19..1a85edf028 100644 --- a/internal/rootcoord/util.go +++ b/internal/rootcoord/util.go @@ -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) { diff --git a/internal/types/types.go b/internal/types/types.go index 32a53ce309..ea6eda06ad 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -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 diff --git a/internal/util/constant.go b/internal/util/constant.go index c060424bb0..c60a5acbf5 100644 --- a/internal/util/constant.go +++ b/internal/util/constant.go @@ -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)] +} diff --git a/internal/util/errorutil/util.go b/internal/util/errorutil/util.go index d3289c6365..45c1fa1922 100644 --- a/internal/util/errorutil/util.go +++ b/internal/util/errorutil/util.go @@ -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") +} diff --git a/internal/util/funcutil/func.go b/internal/util/funcutil/func.go index f0f9624fd3..77dbbfdd1c 100644 --- a/internal/util/funcutil/func.go +++ b/internal/util/funcutil/func.go @@ -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 +} diff --git a/internal/util/funcutil/func_test.go b/internal/util/funcutil/func_test.go index 7b69326e74..beb0cfea7f 100644 --- a/internal/util/funcutil/func_test.go +++ b/internal/util/funcutil/func_test.go @@ -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) +} diff --git a/internal/util/funcutil/policy.go b/internal/util/funcutil/policy.go new file mode 100644 index 0000000000..c0f1ba81ff --- /dev/null +++ b/internal/util/funcutil/policy.go @@ -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) +} diff --git a/internal/util/funcutil/policy_test.go b/internal/util/funcutil/policy_test.go new file mode 100644 index 0000000000..4207198ee3 --- /dev/null +++ b/internal/util/funcutil/policy_test.go @@ -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")) +} diff --git a/internal/util/metricsinfo/container_test.go b/internal/util/metricsinfo/container_test_linux.go similarity index 97% rename from internal/util/metricsinfo/container_test.go rename to internal/util/metricsinfo/container_test_linux.go index efec4a7518..4937df005f 100644 --- a/internal/util/metricsinfo/container_test.go +++ b/internal/util/metricsinfo/container_test_linux.go @@ -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 ( diff --git a/internal/util/mock/grpc_rootcoord_client.go b/internal/util/mock/grpc_rootcoord_client.go index 82bab42efb..d255c00223 100644 --- a/internal/util/mock/grpc_rootcoord_client.go +++ b/internal/util/mock/grpc_rootcoord_client.go @@ -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 } diff --git a/internal/util/paramtable/component_param.go b/internal/util/paramtable/component_param.go index 4cec32bc2e..e61583e4e9 100644 --- a/internal/util/paramtable/component_param.go +++ b/internal/util/paramtable/component_param.go @@ -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 { diff --git a/internal/util/paramtable/component_param_test.go b/internal/util/paramtable/component_param_test.go index f771fbaa9f..3727a2d58d 100644 --- a/internal/util/paramtable/component_param_test.go +++ b/internal/util/paramtable/component_param_test.go @@ -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) { diff --git a/internal/util/typeutil/cache.go b/internal/util/typeutil/cache.go new file mode 100644 index 0000000000..9ea4c12b2e --- /dev/null +++ b/internal/util/typeutil/cache.go @@ -0,0 +1,15 @@ +package typeutil + +type CacheOpType int32 + +const ( + CacheAddUserToRole CacheOpType = iota + 1 + CacheRemoveUserFromRole + CacheGrantPrivilege + CacheRevokePrivilege +) + +type CacheOp struct { + OpType CacheOpType + OpKey string +} diff --git a/internal/util/typeutil/string_util.go b/internal/util/typeutil/string_util.go index 48c3905a7c..e0ed76b85a 100644 --- a/internal/util/typeutil/string_util.go +++ b/internal/util/typeutil/string_util.go @@ -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) +}