From d192f2b3bc3e5e8613a15530574c334b6df32d32 Mon Sep 17 00:00:00 2001 From: moogacs Date: Wed, 13 Nov 2024 11:49:27 +0100 Subject: [PATCH 1/5] raft(rbac): persist RBCA changes in all nodes --- adapters/handlers/rest/configure_api.go | 4 +- cluster/proto/api/message.pb.go | 320 ++++++++++-------- cluster/proto/api/message.proto | 7 + cluster/proto/api/rbac_requests.go | 39 +++ .../api/{request.go => schama_requests.go} | 0 cluster/raft_rbac_apply_endpoints.go | 118 +++++++ cluster/raft_rbac_query_endpoints.go | 28 ++ cluster/rbac/manager.go | 91 +++++ cluster/store.go | 9 + cluster/store_apply.go | 21 ++ test/acceptance/authz/roles_test.go | 95 ++++++ tools/dev/run_dev_server.sh | 125 +++++-- 12 files changed, 688 insertions(+), 169 deletions(-) create mode 100644 cluster/proto/api/rbac_requests.go rename cluster/proto/api/{request.go => schama_requests.go} (100%) create mode 100644 cluster/raft_rbac_apply_endpoints.go create mode 100644 cluster/raft_rbac_query_endpoints.go create mode 100644 cluster/rbac/manager.go diff --git a/adapters/handlers/rest/configure_api.go b/adapters/handlers/rest/configure_api.go index 417eafb1b71..a0b9f84a65c 100644 --- a/adapters/handlers/rest/configure_api.go +++ b/adapters/handlers/rest/configure_api.go @@ -467,6 +467,7 @@ func MakeAppState(ctx context.Context, options *swag.CommandLineOptionsGroup) *s FQDNResolverTLD: appState.ServerConfig.Config.Raft.FQDNResolverTLD, SentryEnabled: appState.ServerConfig.Config.Sentry.Enabled, ClassTenantDataEvents: classTenantDataEvents, + AuthzController: appState.AuthzController, } for _, name := range appState.ServerConfig.Config.Raft.Join[:rConfig.BootstrapExpect] { if strings.Contains(name, rConfig.NodeID) { @@ -476,6 +477,7 @@ func MakeAppState(ctx context.Context, options *swag.CommandLineOptionsGroup) *s } appState.ClusterService = rCluster.New(appState.Cluster, rConfig) + migrator.SetCluster(appState.ClusterService.Raft) executor := schema.NewExecutor(migrator, @@ -658,7 +660,7 @@ func configureAPI(api *operations.WeaviateAPI) http.Handler { appState.Authorizer, appState.Logger, appState.Modules) - setupAuthZHandlers(api, appState.AuthzController, appState.Metrics, appState.Authorizer, appState.Logger) + setupAuthZHandlers(api, appState.ClusterService.Raft, appState.Metrics, appState.Authorizer, appState.Logger) setupSchemaHandlers(api, appState.SchemaManager, appState.Metrics, appState.Logger) objectsManager := objects.NewManager(appState.Locks, appState.SchemaManager, appState.ServerConfig, appState.Logger, diff --git a/cluster/proto/api/message.pb.go b/cluster/proto/api/message.pb.go index c8e224b912e..6f823416a50 100644 --- a/cluster/proto/api/message.pb.go +++ b/cluster/proto/api/message.pb.go @@ -25,18 +25,23 @@ const ( type ApplyRequest_Type int32 const ( - ApplyRequest_TYPE_UNSPECIFIED ApplyRequest_Type = 0 - ApplyRequest_TYPE_ADD_CLASS ApplyRequest_Type = 1 - ApplyRequest_TYPE_UPDATE_CLASS ApplyRequest_Type = 2 - ApplyRequest_TYPE_DELETE_CLASS ApplyRequest_Type = 3 - ApplyRequest_TYPE_RESTORE_CLASS ApplyRequest_Type = 4 - ApplyRequest_TYPE_ADD_PROPERTY ApplyRequest_Type = 5 - ApplyRequest_TYPE_UPDATE_SHARD_STATUS ApplyRequest_Type = 10 - ApplyRequest_TYPE_ADD_TENANT ApplyRequest_Type = 16 - ApplyRequest_TYPE_UPDATE_TENANT ApplyRequest_Type = 17 - ApplyRequest_TYPE_DELETE_TENANT ApplyRequest_Type = 18 - ApplyRequest_TYPE_TENANT_PROCESS ApplyRequest_Type = 19 - ApplyRequest_TYPE_STORE_SCHEMA_V1 ApplyRequest_Type = 99 + ApplyRequest_TYPE_UNSPECIFIED ApplyRequest_Type = 0 + ApplyRequest_TYPE_ADD_CLASS ApplyRequest_Type = 1 + ApplyRequest_TYPE_UPDATE_CLASS ApplyRequest_Type = 2 + ApplyRequest_TYPE_DELETE_CLASS ApplyRequest_Type = 3 + ApplyRequest_TYPE_RESTORE_CLASS ApplyRequest_Type = 4 + ApplyRequest_TYPE_ADD_PROPERTY ApplyRequest_Type = 5 + ApplyRequest_TYPE_UPDATE_SHARD_STATUS ApplyRequest_Type = 10 + ApplyRequest_TYPE_ADD_TENANT ApplyRequest_Type = 16 + ApplyRequest_TYPE_UPDATE_TENANT ApplyRequest_Type = 17 + ApplyRequest_TYPE_DELETE_TENANT ApplyRequest_Type = 18 + ApplyRequest_TYPE_TENANT_PROCESS ApplyRequest_Type = 19 + ApplyRequest_TYPE_UPSERT_ROLES ApplyRequest_Type = 60 + ApplyRequest_TYPE_DELETE_ROLES ApplyRequest_Type = 61 + ApplyRequest_TYPE_REMOVE_PERMISSIONS ApplyRequest_Type = 62 + ApplyRequest_TYPE_ADD_ROLES_FOR_USER ApplyRequest_Type = 63 + ApplyRequest_TYPE_REVOKE_ROLES_FOR_USER ApplyRequest_Type = 64 + ApplyRequest_TYPE_STORE_SCHEMA_V1 ApplyRequest_Type = 99 ) // Enum value maps for ApplyRequest_Type. @@ -53,21 +58,31 @@ var ( 17: "TYPE_UPDATE_TENANT", 18: "TYPE_DELETE_TENANT", 19: "TYPE_TENANT_PROCESS", + 60: "TYPE_UPSERT_ROLES", + 61: "TYPE_DELETE_ROLES", + 62: "TYPE_REMOVE_PERMISSIONS", + 63: "TYPE_ADD_ROLES_FOR_USER", + 64: "TYPE_REVOKE_ROLES_FOR_USER", 99: "TYPE_STORE_SCHEMA_V1", } ApplyRequest_Type_value = map[string]int32{ - "TYPE_UNSPECIFIED": 0, - "TYPE_ADD_CLASS": 1, - "TYPE_UPDATE_CLASS": 2, - "TYPE_DELETE_CLASS": 3, - "TYPE_RESTORE_CLASS": 4, - "TYPE_ADD_PROPERTY": 5, - "TYPE_UPDATE_SHARD_STATUS": 10, - "TYPE_ADD_TENANT": 16, - "TYPE_UPDATE_TENANT": 17, - "TYPE_DELETE_TENANT": 18, - "TYPE_TENANT_PROCESS": 19, - "TYPE_STORE_SCHEMA_V1": 99, + "TYPE_UNSPECIFIED": 0, + "TYPE_ADD_CLASS": 1, + "TYPE_UPDATE_CLASS": 2, + "TYPE_DELETE_CLASS": 3, + "TYPE_RESTORE_CLASS": 4, + "TYPE_ADD_PROPERTY": 5, + "TYPE_UPDATE_SHARD_STATUS": 10, + "TYPE_ADD_TENANT": 16, + "TYPE_UPDATE_TENANT": 17, + "TYPE_DELETE_TENANT": 18, + "TYPE_TENANT_PROCESS": 19, + "TYPE_UPSERT_ROLES": 60, + "TYPE_DELETE_ROLES": 61, + "TYPE_REMOVE_PERMISSIONS": 62, + "TYPE_ADD_ROLES_FOR_USER": 63, + "TYPE_REVOKE_ROLES_FOR_USER": 64, + "TYPE_STORE_SCHEMA_V1": 99, } ) @@ -1139,7 +1154,7 @@ var file_api_message_proto_rawDesc = []byte{ 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc7, 0x03, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcf, 0x04, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, @@ -1149,7 +1164,7 @@ var file_api_message_proto_rawDesc = []byte{ 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, - 0x75, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0xa3, 0x02, 0x0a, 0x04, 0x54, 0x79, + 0x75, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0xab, 0x03, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x44, 0x44, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, @@ -1166,134 +1181,143 @@ var file_api_message_proto_rawDesc = []byte{ 0x4e, 0x54, 0x10, 0x11, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x54, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x43, - 0x45, 0x53, 0x53, 0x10, 0x13, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, - 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x56, 0x31, 0x10, 0x63, 0x22, - 0x41, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x22, 0xa5, 0x02, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0xb1, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, - 0x54, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x45, 0x53, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x10, 0x02, - 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x45, 0x4e, - 0x41, 0x4e, 0x54, 0x53, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, - 0x45, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x04, - 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x45, 0x4e, - 0x41, 0x4e, 0x54, 0x53, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x53, 0x10, 0x05, 0x12, 0x1b, 0x0a, - 0x17, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x49, - 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x06, 0x22, 0x29, 0x0a, 0x0d, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x75, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x54, 0x65, 0x6e, 0x61, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, - 0x3b, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x74, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x78, 0x0a, 0x14, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, - 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6e, 0x61, 0x6e, - 0x74, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x3c, 0x0a, 0x02, 0x6f, 0x70, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, + 0x45, 0x53, 0x53, 0x10, 0x13, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x50, + 0x53, 0x45, 0x52, 0x54, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x53, 0x10, 0x3c, 0x12, 0x15, 0x0a, 0x11, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x52, 0x4f, 0x4c, 0x45, + 0x53, 0x10, 0x3d, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, + 0x56, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x3e, + 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x44, 0x44, 0x5f, 0x52, 0x4f, 0x4c, + 0x45, 0x53, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x3f, 0x12, 0x1e, 0x0a, + 0x1a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x56, 0x4f, 0x4b, 0x45, 0x5f, 0x52, 0x4f, 0x4c, + 0x45, 0x53, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x40, 0x12, 0x18, 0x0a, + 0x14, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x43, 0x48, 0x45, + 0x4d, 0x41, 0x5f, 0x56, 0x31, 0x10, 0x63, 0x22, 0x41, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xa5, 0x02, 0x0a, 0x0c, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, + 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0xb1, + 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, + 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x45, + 0x53, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, + 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x54, 0x53, 0x10, 0x03, 0x12, 0x18, + 0x0a, 0x14, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, + 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x54, 0x53, 0x5f, 0x53, 0x48, 0x41, + 0x52, 0x44, 0x53, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, + 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x10, 0x06, 0x22, 0x29, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x75, 0x0a, + 0x11, 0x41, 0x64, 0x64, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, + 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x74, 0x65, 0x6e, + 0x61, 0x6e, 0x74, 0x73, 0x22, 0x78, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x07, + 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xcc, + 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x12, 0x3c, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, + 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x4f, 0x70, 0x52, 0x02, 0x6f, 0x70, 0x12, + 0x39, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, + 0x6e, 0x74, 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x22, 0x41, 0x0a, 0x02, 0x4f, 0x70, + 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4f, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x12, + 0x0c, 0x0a, 0x08, 0x4f, 0x50, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x03, 0x22, 0xa0, 0x02, + 0x0a, 0x14, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4e, 0x0a, 0x06, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x77, 0x65, 0x61, + 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x11, 0x74, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x2e, 0x4f, 0x70, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, + 0x52, 0x10, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, + 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, + 0x52, 0x45, 0x45, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x46, 0x52, 0x45, 0x45, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, + 0x22, 0x30, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, + 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x73, 0x22, 0x34, 0x0a, 0x06, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0x8d, 0x04, 0x0a, 0x0e, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, + 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, - 0x6e, 0x74, 0x22, 0x41, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x4f, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, - 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4f, 0x50, 0x5f, 0x41, 0x42, - 0x4f, 0x52, 0x54, 0x10, 0x03, 0x22, 0xa0, 0x02, 0x0a, 0x14, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, - 0x64, 0x65, 0x12, 0x4e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, - 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x11, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, + 0x50, 0x65, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4a, 0x6f, 0x69, + 0x6e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x6b, 0x0a, 0x0a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, - 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x10, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, - 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x06, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5a, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x46, 0x52, - 0x45, 0x45, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x30, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x18, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x34, 0x0a, 0x06, 0x54, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x32, 0x8d, 0x04, 0x0a, 0x0e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x65, 0x65, - 0x72, 0x12, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2d, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x65, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x77, - 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, - 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x0a, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, + 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x77, 0x65, + 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x05, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x27, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, + 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x05, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x27, 0x2e, - 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, - 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x77, 0x65, - 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0xe1, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, - 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x42, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, - 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, - 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x69, - 0xa2, 0x02, 0x03, 0x57, 0x49, 0x43, 0xaa, 0x02, 0x19, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, - 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0xca, 0x02, 0x19, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x5c, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0xe2, 0x02, - 0x25, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x5c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1b, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, - 0x65, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x77, + 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xe1, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, + 0x2e, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x42, 0x0c, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2f, + 0x77, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0xa2, 0x02, 0x03, 0x57, 0x49, 0x43, 0xaa, 0x02, + 0x19, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0xca, 0x02, 0x19, 0x57, 0x65, 0x61, + 0x76, 0x69, 0x61, 0x74, 0x65, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0xe2, 0x02, 0x25, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, + 0x65, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x1b, 0x57, 0x65, 0x61, 0x76, 0x69, 0x61, 0x74, 0x65, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/cluster/proto/api/message.proto b/cluster/proto/api/message.proto index 4d483af3f00..1d6a549889b 100644 --- a/cluster/proto/api/message.proto +++ b/cluster/proto/api/message.proto @@ -53,6 +53,13 @@ message ApplyRequest { TYPE_DELETE_TENANT = 18; TYPE_TENANT_PROCESS = 19; + + TYPE_UPSERT_ROLES = 60; + TYPE_DELETE_ROLES = 61; + TYPE_REMOVE_PERMISSIONS = 62; + TYPE_ADD_ROLES_FOR_USER = 63; + TYPE_REVOKE_ROLES_FOR_USER = 64; + TYPE_STORE_SCHEMA_V1 = 99; } Type type = 1; diff --git a/cluster/proto/api/rbac_requests.go b/cluster/proto/api/rbac_requests.go new file mode 100644 index 00000000000..3672eeeb924 --- /dev/null +++ b/cluster/proto/api/rbac_requests.go @@ -0,0 +1,39 @@ +// _ _ +// __ _____ __ ___ ___ __ _| |_ ___ +// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ +// \ V V / __/ (_| |\ V /| | (_| | || __/ +// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| +// +// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. +// +// CONTACT: hello@weaviate.io +// + +package api + +import ( + "github.com/weaviate/weaviate/entities/models" +) + +type CreateRolesRequest struct { + Roles []*models.Role +} + +type DeleteRolesRequest struct { + Roles []string +} + +type RemovePermissionsRequest struct { + Role string + Permissions []*models.Permission +} + +type AddRolesForUsersRequest struct { + User string + Roles []string +} + +type RevokeRolesForUserRequest struct { + User string + Roles []string +} diff --git a/cluster/proto/api/request.go b/cluster/proto/api/schama_requests.go similarity index 100% rename from cluster/proto/api/request.go rename to cluster/proto/api/schama_requests.go diff --git a/cluster/raft_rbac_apply_endpoints.go b/cluster/raft_rbac_apply_endpoints.go new file mode 100644 index 00000000000..3bec7440b6f --- /dev/null +++ b/cluster/raft_rbac_apply_endpoints.go @@ -0,0 +1,118 @@ +// _ _ +// __ _____ __ ___ ___ __ _| |_ ___ +// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ +// \ V V / __/ (_| |\ V /| | (_| | || __/ +// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| +// +// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. +// +// CONTACT: hello@weaviate.io +// + +package cluster + +import ( + "context" + "encoding/json" + "fmt" + + cmd "github.com/weaviate/weaviate/cluster/proto/api" + "github.com/weaviate/weaviate/cluster/schema" + "github.com/weaviate/weaviate/entities/models" +) + +func (s *Raft) UpsertRoles(roles ...*models.Role) error { + if len(roles) == 0 { + return fmt.Errorf("no roles to create: %w", schema.ErrBadRequest) + } + + req := cmd.CreateRolesRequest{Roles: roles} + subCommand, err := json.Marshal(&req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + command := &cmd.ApplyRequest{ + Type: cmd.ApplyRequest_TYPE_UPSERT_ROLES, + SubCommand: subCommand, + } + if _, err := s.Execute(context.Background(), command); err != nil { + return err + } + return nil +} + +func (s *Raft) DeleteRoles(names ...string) error { + if len(names) == 0 { + return fmt.Errorf("no roles to delete: %w", schema.ErrBadRequest) + } + req := cmd.DeleteRolesRequest{Roles: names} + subCommand, err := json.Marshal(&req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + command := &cmd.ApplyRequest{ + Type: cmd.ApplyRequest_TYPE_DELETE_ROLES, + SubCommand: subCommand, + } + if _, err := s.Execute(context.Background(), command); err != nil { + return err + } + return nil +} + +func (s *Raft) RemovePermissions(role string, permissions []*models.Permission) error { + if role == "" { + return fmt.Errorf("no roles to remove permissions from: %w", schema.ErrBadRequest) + } + req := cmd.RemovePermissionsRequest{Role: role, Permissions: permissions} + subCommand, err := json.Marshal(&req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + command := &cmd.ApplyRequest{ + Type: cmd.ApplyRequest_TYPE_REMOVE_PERMISSIONS, + SubCommand: subCommand, + } + if _, err := s.Execute(context.Background(), command); err != nil { + return err + } + return nil +} + +func (s *Raft) AddRolesForUser(user string, roles []string) error { + if len(roles) == 0 { + return fmt.Errorf("no roles to assign: %w", schema.ErrBadRequest) + } + req := cmd.AddRolesForUsersRequest{User: user, Roles: roles} + subCommand, err := json.Marshal(&req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + command := &cmd.ApplyRequest{ + Type: cmd.ApplyRequest_TYPE_ADD_ROLES_FOR_USER, + SubCommand: subCommand, + } + if _, err := s.Execute(context.Background(), command); err != nil { + return err + } + return nil +} + +func (s *Raft) RevokeRolesForUser(user string, roles ...string) error { + if len(roles) == 0 { + return fmt.Errorf("no roles to revoke: %w", schema.ErrBadRequest) + } + req := cmd.RevokeRolesForUserRequest{User: user, Roles: roles} + subCommand, err := json.Marshal(&req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + command := &cmd.ApplyRequest{ + Type: cmd.ApplyRequest_TYPE_REVOKE_ROLES_FOR_USER, + SubCommand: subCommand, + } + if _, err := s.Execute(context.Background(), command); err != nil { + return err + } + return nil +} diff --git a/cluster/raft_rbac_query_endpoints.go b/cluster/raft_rbac_query_endpoints.go new file mode 100644 index 00000000000..e357ae1dd5b --- /dev/null +++ b/cluster/raft_rbac_query_endpoints.go @@ -0,0 +1,28 @@ +// _ _ +// __ _____ __ ___ ___ __ _| |_ ___ +// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ +// \ V V / __/ (_| |\ V /| | (_| | || __/ +// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| +// +// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. +// +// CONTACT: hello@weaviate.io +// + +package cluster + +import ( + "github.com/weaviate/weaviate/entities/models" +) + +func (s *Raft) GetRoles(names ...string) ([]*models.Role, error) { + return s.store.authZManager.GetRoles(names...) +} + +func (s *Raft) GetRolesForUser(user string) ([]*models.Role, error) { + return s.store.authZManager.GetRolesForUser(user) +} + +func (s *Raft) GetUsersForRole(role string) ([]string, error) { + return s.store.authZManager.GetUsersForRole(role) +} diff --git a/cluster/rbac/manager.go b/cluster/rbac/manager.go new file mode 100644 index 00000000000..a0cd9c13062 --- /dev/null +++ b/cluster/rbac/manager.go @@ -0,0 +1,91 @@ +// _ _ +// __ _____ __ ___ ___ __ _| |_ ___ +// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ +// \ V V / __/ (_| |\ V /| | (_| | || __/ +// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| +// +// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. +// +// CONTACT: hello@weaviate.io +// + +package rbac + +import ( + "encoding/json" + "errors" + "fmt" + + "github.com/sirupsen/logrus" + cmd "github.com/weaviate/weaviate/cluster/proto/api" + "github.com/weaviate/weaviate/entities/models" + "github.com/weaviate/weaviate/usecases/auth/authorization" +) + +var ErrBadRequest = errors.New("bad request") + +type Manager struct { + authZ authorization.Controller + logger logrus.FieldLogger +} + +func NewManager(authZ authorization.Controller, logger logrus.FieldLogger) *Manager { + return &Manager{authZ: authZ, logger: logger} +} + +func (m *Manager) GetRoles(names ...string) ([]*models.Role, error) { + return m.authZ.GetRoles(names...) +} + +func (m *Manager) GetRolesForUser(user string) ([]*models.Role, error) { + return m.authZ.GetRolesForUser(user) +} + +func (m *Manager) GetUsersForRole(role string) ([]string, error) { + return m.authZ.GetUsersForRole(role) +} + +func (m *Manager) UpsertRoles(c *cmd.ApplyRequest) error { + req := &cmd.CreateRolesRequest{} + if err := json.Unmarshal(c.SubCommand, req); err != nil { + return fmt.Errorf("%w: %w", ErrBadRequest, err) + } + + return m.authZ.UpsertRoles(req.Roles...) +} + +func (m *Manager) DeleteRoles(c *cmd.ApplyRequest) error { + req := &cmd.DeleteRolesRequest{} + if err := json.Unmarshal(c.SubCommand, req); err != nil { + return fmt.Errorf("%w: %w", ErrBadRequest, err) + } + + return m.authZ.DeleteRoles(req.Roles...) +} + +func (m *Manager) AddRolesForUser(c *cmd.ApplyRequest) error { + req := &cmd.AddRolesForUsersRequest{} + if err := json.Unmarshal(c.SubCommand, req); err != nil { + return fmt.Errorf("%w: %w", ErrBadRequest, err) + } + + return m.authZ.AddRolesForUser(req.User, req.Roles) +} + +func (m *Manager) RemovePermissions(c *cmd.ApplyRequest) error { + req := &cmd.RemovePermissionsRequest{} + if err := json.Unmarshal(c.SubCommand, req); err != nil { + return fmt.Errorf("%w: %w", ErrBadRequest, err) + } + + return m.authZ.RemovePermissions(req.Role, req.Permissions) +} + +func (m *Manager) RevokeRolesForUser(c *cmd.ApplyRequest) error { + req := &cmd.RevokeRolesForUserRequest{} + if err := json.Unmarshal(c.SubCommand, req); err != nil { + return fmt.Errorf("%w: %w", ErrBadRequest, err) + } + + return m.authZ.RevokeRolesForUser(req.User, req.Roles...) +} diff --git a/cluster/store.go b/cluster/store.go index 58b3d1aecd4..c2dddb57078 100644 --- a/cluster/store.go +++ b/cluster/store.go @@ -24,11 +24,13 @@ import ( enterrors "github.com/weaviate/weaviate/entities/errors" "github.com/weaviate/weaviate/exp/metadata" + "github.com/weaviate/weaviate/usecases/auth/authorization" "github.com/hashicorp/raft" raftbolt "github.com/hashicorp/raft-boltdb/v2" "github.com/sirupsen/logrus" "github.com/weaviate/weaviate/cluster/log" + "github.com/weaviate/weaviate/cluster/rbac" "github.com/weaviate/weaviate/cluster/resolver" "github.com/weaviate/weaviate/cluster/schema" "github.com/weaviate/weaviate/cluster/types" @@ -142,6 +144,8 @@ type Config struct { // being frozen happen, with the goal of being able to alert the metadata nodes. This // channel will be nil if the metadata server is not enabled. ClassTenantDataEvents chan metadata.ClassTenant + + AuthzController authorization.Controller } // Store is the implementation of RAFT on this local node. It will handle the local schema and RAFT operations (startup, @@ -184,6 +188,10 @@ type Store struct { // schemaManager is responsible for applying changes committed by RAFT to the schema representation & querying the // schema schemaManager *schema.SchemaManager + + // authZManager is responsible for applying/querying changes committed by RAFT to the rbac representation + authZManager *rbac.Manager + // lastAppliedIndexToDB represents the index of the last applied command when the store is opened. lastAppliedIndexToDB atomic.Uint64 // / lastAppliedIndex index of latest update to the store @@ -223,6 +231,7 @@ func NewFSM(cfg Config) Store { applyTimeout: time.Second * 20, raftResolver: raftResolver, schemaManager: schemaManager, + authZManager: rbac.NewManager(cfg.AuthzController, cfg.Logger), } } diff --git a/cluster/store_apply.go b/cluster/store_apply.go index 378b94907f4..04b363a0308 100644 --- a/cluster/store_apply.go +++ b/cluster/store_apply.go @@ -192,6 +192,27 @@ func (st *Store) Apply(l *raft.Log) interface{} { ret.Error = st.StoreSchemaV1() } + case api.ApplyRequest_TYPE_UPSERT_ROLES: + f = func() { + ret.Error = st.authZManager.UpsertRoles(&cmd) + } + case api.ApplyRequest_TYPE_DELETE_ROLES: + f = func() { + ret.Error = st.authZManager.DeleteRoles(&cmd) + } + case api.ApplyRequest_TYPE_REMOVE_PERMISSIONS: + f = func() { + ret.Error = st.authZManager.RemovePermissions(&cmd) + } + case api.ApplyRequest_TYPE_ADD_ROLES_FOR_USER: + f = func() { + ret.Error = st.authZManager.AddRolesForUser(&cmd) + } + case api.ApplyRequest_TYPE_REVOKE_ROLES_FOR_USER: + f = func() { + ret.Error = st.authZManager.RevokeRolesForUser(&cmd) + } + default: // This could occur when a new command has been introduced in a later app version // At this point, we need to panic so that the app undergo an upgrade during restart diff --git a/test/acceptance/authz/roles_test.go b/test/acceptance/authz/roles_test.go index 494628b61bc..e3079d3e27c 100644 --- a/test/acceptance/authz/roles_test.go +++ b/test/acceptance/authz/roles_test.go @@ -201,6 +201,101 @@ func TestAuthzRolesJourney(t *testing.T) { }) } +func TestAuthzRolesMultiNodeJourney(t *testing.T) { + t.Parallel() + + existingUser := "existing-user" + existingKey := "existing-key" + existingRole := "admin" + + testRole := "test-role" + testAction1 := "create_collections" + testAction2 := "delete_collections" + all := "*" + + clientAuth := helper.CreateAuth(existingKey) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + compose, err := docker.New().WithWeaviateCluster(3).WithRBAC().WithRbacUser(existingUser, existingKey, existingRole).Start(ctx) + require.Nil(t, err) + + defer func() { + if err := compose.Terminate(ctx); err != nil { + t.Fatalf("failed to terminate test containers: %v", err) + } + }() + + helper.SetupClient(compose.GetWeaviate().URI()) + defer helper.ResetClient() + + t.Run("add role while 1 node is down", func(t *testing.T) { + t.Run("get all roles before create", func(t *testing.T) { + res, err := helper.Client(t).Authz.GetRoles(authz.NewGetRolesParams(), clientAuth) + require.Nil(t, err) + require.Equal(t, 3, len(res.Payload)) + }) + + t.Run("StopNode-3", func(t *testing.T) { + require.Nil(t, compose.StopAt(ctx, 2, nil)) + }) + + t.Run("create role", func(t *testing.T) { + _, err = helper.Client(t).Authz.CreateRole( + authz.NewCreateRoleParams().WithBody(&models.Role{ + Name: &testRole, + Permissions: []*models.Permission{{ + Action: &testAction1, + Collection: &all, + }}, + }), + clientAuth, + ) + require.Nil(t, err) + }) + + t.Run("StartNode-3", func(t *testing.T) { + require.Nil(t, compose.StartAt(ctx, 2)) + }) + + helper.SetupClient(compose.GetWeaviateNode3().URI()) + + t.Run("get all roles after create", func(t *testing.T) { + res, err := helper.Client(t).Authz.GetRoles(authz.NewGetRolesParams(), clientAuth) + require.Nil(t, err) + require.Equal(t, 4, len(res.Payload)) + }) + + t.Run("get role by name", func(t *testing.T) { + res, err := helper.Client(t).Authz.GetRole(authz.NewGetRoleParams().WithID(testRole), clientAuth) + require.Nil(t, err) + require.Equal(t, testRole, *res.Payload.Name) + require.Equal(t, 1, len(res.Payload.Permissions)) + require.Equal(t, testAction1, *res.Payload.Permissions[0].Action) + }) + + t.Run("add permission to role Node3", func(t *testing.T) { + _, err := helper.Client(t).Authz.AddPermissions(authz.NewAddPermissionsParams().WithBody(authz.AddPermissionsBody{ + Name: &testRole, + Permissions: []*models.Permission{{Action: &testAction2, Collection: &all}}, + }), clientAuth) + require.Nil(t, err) + }) + + helper.SetupClient(compose.GetWeaviate().URI()) + + t.Run("get role by name after adding permission Node1", func(t *testing.T) { + res, err := helper.Client(t).Authz.GetRole(authz.NewGetRoleParams().WithID(testRole), clientAuth) + require.Nil(t, err) + require.Equal(t, testRole, *res.Payload.Name) + require.Equal(t, 2, len(res.Payload.Permissions)) + require.Equal(t, testAction1, *res.Payload.Permissions[0].Action) + require.Equal(t, testAction2, *res.Payload.Permissions[1].Action) + }) + }) +} + func String(s string) *string { return &s } diff --git a/tools/dev/run_dev_server.sh b/tools/dev/run_dev_server.sh index 9fdea468b0e..cda2a3da04f 100755 --- a/tools/dev/run_dev_server.sh +++ b/tools/dev/run_dev_server.sh @@ -65,26 +65,111 @@ case $CONFIG in --write-timeout=600s ;; - local-single-node-rbac) - AUTHENTICATION_APIKEY_ENABLED=true \ - AUTHORIZATION_ENABLE_RBAC=true \ - AUTHENTICATION_APIKEY_ALLOWED_KEYS='jane-secret-key,ian-secret-key,jp-secret-key' \ - AUTHENTICATION_APIKEY_USERS='jane@doe.com,ian-smith,jp-hwang' \ - AUTHENTICATION_APIKEY_ROLES='viewer,editor,admin' \ - PERSISTENCE_DATA_PATH="./data-weaviate-0" \ - BACKUP_FILESYSTEM_PATH="${PWD}/backups-weaviate-0" \ - ENABLE_MODULES="backup-filesystem" \ - CLUSTER_IN_LOCALHOST=true \ - CLUSTER_GOSSIP_BIND_PORT="7100" \ - CLUSTER_DATA_BIND_PORT="7101" \ - RAFT_BOOTSTRAP_EXPECT=1 \ - go_run ./cmd/weaviate-server \ - --scheme http \ - --host "127.0.0.1" \ - --port 8080 \ - --read-timeout=600s \ - --write-timeout=600s - ;; + local-single-node-rbac) + AUTHENTICATION_APIKEY_ENABLED=true \ + AUTHORIZATION_ENABLE_RBAC=true \ + AUTHENTICATION_APIKEY_ALLOWED_KEYS='jane-secret-key,ian-secret-key,jp-secret-key' \ + AUTHENTICATION_APIKEY_USERS='jane@doe.com,ian-smith,jp-hwang' \ + AUTHENTICATION_APIKEY_ROLES='viewer,editor,admin' \ + PERSISTENCE_DATA_PATH="./data-weaviate-0" \ + BACKUP_FILESYSTEM_PATH="${PWD}/backups-weaviate-0" \ + ENABLE_MODULES="backup-filesystem" \ + CLUSTER_IN_LOCALHOST=true \ + CLUSTER_GOSSIP_BIND_PORT="7100" \ + CLUSTER_DATA_BIND_PORT="7101" \ + RAFT_BOOTSTRAP_EXPECT=1 \ + go_run ./cmd/weaviate-server \ + --scheme http \ + --host "127.0.0.1" \ + --port 8080 \ + --read-timeout=600s \ + --write-timeout=600s + ;; + + local-first-rbac) + CONTEXTIONARY_URL=localhost:9999 \ + AUTHENTICATION_APIKEY_ENABLED=true \ + AUTHORIZATION_ENABLE_RBAC=true \ + AUTHENTICATION_APIKEY_ALLOWED_KEYS='jane-secret-key,ian-secret-key,jp-secret-key' \ + AUTHENTICATION_APIKEY_USERS='jane@doe.com,ian-smith,jp-hwang' \ + AUTHENTICATION_APIKEY_ROLES='viewer,editor,admin' \ + PERSISTENCE_DATA_PATH="${PERSISTENCE_DATA_PATH}-weaviate-0" \ + BACKUP_FILESYSTEM_PATH="${PWD}/backups-weaviate-0" \ + DEFAULT_VECTORIZER_MODULE=text2vec-contextionary \ + ENABLE_MODULES="text2vec-contextionary,backup-filesystem" \ + PROMETHEUS_MONITORING_PORT="2112" \ + CLUSTER_IN_LOCALHOST=true \ + CLUSTER_GOSSIP_BIND_PORT="7100" \ + CLUSTER_DATA_BIND_PORT="7101" \ + RAFT_JOIN="weaviate-0:8300,weaviate-1:8302,weaviate-2:8304" \ + RAFT_BOOTSTRAP_EXPECT=3 \ + go_run ./cmd/weaviate-server \ + --scheme http \ + --host "127.0.0.1" \ + --port 8080 \ + --read-timeout=600s \ + --write-timeout=600s + ;; + + local-second-rbac) + GRPC_PORT=50052 \ + CONTEXTIONARY_URL=localhost:9999 \ + AUTHENTICATION_APIKEY_ENABLED=true \ + AUTHORIZATION_ENABLE_RBAC=true \ + AUTHENTICATION_APIKEY_ALLOWED_KEYS='jane-secret-key,ian-secret-key,jp-secret-key' \ + AUTHENTICATION_APIKEY_USERS='jane@doe.com,ian-smith,jp-hwang' \ + AUTHENTICATION_APIKEY_ROLES='viewer,editor,admin' \ + PERSISTENCE_DATA_PATH="${PERSISTENCE_DATA_PATH}-weaviate-1" \ + BACKUP_FILESYSTEM_PATH="${PWD}/backups-weaviate-1" \ + CLUSTER_HOSTNAME="weaviate-1" \ + CLUSTER_IN_LOCALHOST=true \ + CLUSTER_GOSSIP_BIND_PORT="7102" \ + CLUSTER_DATA_BIND_PORT="7103" \ + CLUSTER_JOIN="localhost:7100" \ + PROMETHEUS_MONITORING_PORT="2113" \ + RAFT_PORT="8302" \ + RAFT_INTERNAL_RPC_PORT="8303" \ + RAFT_JOIN="weaviate-0:8300,weaviate-1:8302,weaviate-2:8304" \ + RAFT_BOOTSTRAP_EXPECT=3 \ + DEFAULT_VECTORIZER_MODULE=text2vec-contextionary \ + ENABLE_MODULES="text2vec-contextionary,backup-filesystem" \ + go_run ./cmd/weaviate-server \ + --scheme http \ + --host "127.0.0.1" \ + --port 8081 \ + --read-timeout=600s \ + --write-timeout=600s + ;; + + local-third-rbac) + GRPC_PORT=50053 \ + CONTEXTIONARY_URL=localhost:9999 \ + AUTHENTICATION_APIKEY_ENABLED=true \ + AUTHORIZATION_ENABLE_RBAC=true \ + AUTHENTICATION_APIKEY_ALLOWED_KEYS='jane-secret-key,ian-secret-key,jp-secret-key' \ + AUTHENTICATION_APIKEY_USERS='jane@doe.com,ian-smith,jp-hwang' \ + AUTHENTICATION_APIKEY_ROLES='viewer,editor,admin' \ + BACKUP_FILESYSTEM_PATH="${PWD}/backups-weaviate-2" \ + PERSISTENCE_DATA_PATH="${PERSISTENCE_DATA_PATH}-weaviate-2" \ + CLUSTER_HOSTNAME="weaviate-2" \ + CLUSTER_IN_LOCALHOST=true \ + CLUSTER_GOSSIP_BIND_PORT="7104" \ + CLUSTER_DATA_BIND_PORT="7105" \ + CLUSTER_JOIN="localhost:7100" \ + PROMETHEUS_MONITORING_PORT="2114" \ + RAFT_PORT="8304" \ + RAFT_INTERNAL_RPC_PORT="8305" \ + RAFT_JOIN="weaviate-0:8300,weaviate-1:8302,weaviate-2:8304" \ + RAFT_BOOTSTRAP_EXPECT=3 \ + DEFAULT_VECTORIZER_MODULE=text2vec-contextionary \ + ENABLE_MODULES="text2vec-contextionary,backup-filesystem" \ + go_run ./cmd/weaviate-server \ + --scheme http \ + --host "127.0.0.1" \ + --port 8082 \ + --read-timeout=600s \ + --write-timeout=600s + ;; local-development) CONTEXTIONARY_URL=localhost:9999 \ From 90a613ea4bac6cecc7c8330bfb421f859ffe7b2d Mon Sep 17 00:00:00 2001 From: moogacs Date: Wed, 13 Nov 2024 11:56:20 +0100 Subject: [PATCH 2/5] remove parallel from roles acceptance test --- test/acceptance/authz/roles_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/acceptance/authz/roles_test.go b/test/acceptance/authz/roles_test.go index e3079d3e27c..ec0b0455973 100644 --- a/test/acceptance/authz/roles_test.go +++ b/test/acceptance/authz/roles_test.go @@ -25,8 +25,6 @@ import ( ) func TestAuthzRolesJourney(t *testing.T) { - t.Parallel() - existingUser := "existing-user" existingKey := "existing-key" existingRole := "admin" @@ -202,8 +200,6 @@ func TestAuthzRolesJourney(t *testing.T) { } func TestAuthzRolesMultiNodeJourney(t *testing.T) { - t.Parallel() - existingUser := "existing-user" existingKey := "existing-key" existingRole := "admin" From 394390a7a818190fcdd575daa10d08a66ccc8969 Mon Sep 17 00:00:00 2001 From: moogacs Date: Wed, 13 Nov 2024 12:04:22 +0100 Subject: [PATCH 3/5] add EventuallyWithT for getters from different node --- test/acceptance/authz/roles_test.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/acceptance/authz/roles_test.go b/test/acceptance/authz/roles_test.go index ec0b0455973..8c50fd2889b 100644 --- a/test/acceptance/authz/roles_test.go +++ b/test/acceptance/authz/roles_test.go @@ -17,6 +17,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/weaviate/weaviate/client/authz" "github.com/weaviate/weaviate/entities/models" @@ -282,12 +283,15 @@ func TestAuthzRolesMultiNodeJourney(t *testing.T) { helper.SetupClient(compose.GetWeaviate().URI()) t.Run("get role by name after adding permission Node1", func(t *testing.T) { - res, err := helper.Client(t).Authz.GetRole(authz.NewGetRoleParams().WithID(testRole), clientAuth) - require.Nil(t, err) - require.Equal(t, testRole, *res.Payload.Name) - require.Equal(t, 2, len(res.Payload.Permissions)) - require.Equal(t, testAction1, *res.Payload.Permissions[0].Action) - require.Equal(t, testAction2, *res.Payload.Permissions[1].Action) + // EventuallyWithT to handle EC in RAFT reads + require.EventuallyWithT(t, func(collect *assert.CollectT) { + res, err := helper.Client(t).Authz.GetRole(authz.NewGetRoleParams().WithID(testRole), clientAuth) + require.Nil(t, err) + require.Equal(t, testRole, *res.Payload.Name) + require.Equal(t, 2, len(res.Payload.Permissions)) + require.Equal(t, testAction1, *res.Payload.Permissions[0].Action) + require.Equal(t, testAction2, *res.Payload.Permissions[1].Action) + }, 3*time.Second, 500*time.Millisecond) }) }) } From d2363b94ff90889afd43a0cffc10477b47c43837 Mon Sep 17 00:00:00 2001 From: moogacs Date: Wed, 13 Nov 2024 12:05:59 +0100 Subject: [PATCH 4/5] upsert refact --- usecases/auth/authorization/rbac/manager.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/usecases/auth/authorization/rbac/manager.go b/usecases/auth/authorization/rbac/manager.go index 73133fa0011..3ed0c9cc8ed 100644 --- a/usecases/auth/authorization/rbac/manager.go +++ b/usecases/auth/authorization/rbac/manager.go @@ -47,10 +47,8 @@ func (m *manager) UpsertRoles(roles ...*models.Role) error { if err := m.casbin.SavePolicy(); err != nil { return err } - if err := m.casbin.InvalidateCache(); err != nil { - return err - } - return nil + + return m.casbin.InvalidateCache() } func (m *manager) GetRoles(names ...string) ([]*models.Role, error) { From 02c755f0b3a171c64656905cafcaff9592177f59 Mon Sep 17 00:00:00 2001 From: moogacs Date: Wed, 13 Nov 2024 12:34:49 +0100 Subject: [PATCH 5/5] fix typo --- cluster/proto/api/{schama_requests.go => schema_requests.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cluster/proto/api/{schama_requests.go => schema_requests.go} (100%) diff --git a/cluster/proto/api/schama_requests.go b/cluster/proto/api/schema_requests.go similarity index 100% rename from cluster/proto/api/schama_requests.go rename to cluster/proto/api/schema_requests.go