11
11
#include < ydb/core/protos/local.pb.h>
12
12
#include < ydb/core/blobstorage/nodewarden/node_warden_events.h>
13
13
#include < ydb/core/base/auth.h>
14
+ #include < ydb/core/cms/console/console.h>
15
+ #include < ydb/core/cms/console/configs_dispatcher.h>
14
16
15
17
namespace NKikimr ::NGRpcService {
16
18
@@ -136,10 +138,33 @@ void CopyFromConfigResponse(const NKikimrBlobStorage::TConfigResponse &from, Ydb
136
138
137
139
class TReplaceStorageConfigRequest : public TBSConfigRequestGrpc <TReplaceStorageConfigRequest, TEvReplaceStorageConfigRequest,
138
140
Ydb::Config::ReplaceConfigResult> {
139
- public:
140
141
using TBase = TBSConfigRequestGrpc<TReplaceStorageConfigRequest, TEvReplaceStorageConfigRequest, Ydb::Config::ReplaceConfigResult>;
142
+ using TRpcBase = TRpcOperationRequestActor<TReplaceStorageConfigRequest, TEvReplaceStorageConfigRequest>;
143
+ public:
141
144
using TBase::TBase;
142
145
146
+ void Bootstrap (const TActorContext& ctx) {
147
+ TRpcBase::Bootstrap (ctx);
148
+ auto *self = Self ();
149
+ self->OnBootstrap ();
150
+ const auto & request = *GetProtoRequest ();
151
+ auto shim = ConvertConfigReplaceRequest (request);
152
+ if (shim.MainConfig ) {
153
+ if (NYamlConfig::IsDatabaseConfig (*shim.MainConfig )) {
154
+ DatabaseConfig = shim.MainConfig ;
155
+ CheckDatabaseAuthorization ();
156
+ return ;
157
+ }
158
+ }
159
+ if (!NKikimr::IsAdministrator (AppData (), Request_->GetSerializedToken ())) {
160
+ self->Reply (Ydb::StatusIds::UNAUTHORIZED, " User is not a cluster administrator." ,
161
+ NKikimrIssues::TIssuesIds::ACCESS_DENIED, self->ActorContext ());
162
+ return ;
163
+ }
164
+ self->Become (&TReplaceStorageConfigRequest::StateFunc);
165
+ self->Send (MakeBlobStorageNodeWardenID (ctx.SelfID .NodeId ()), new TEvNodeWardenQueryStorageConfig (false ));
166
+ }
167
+
143
168
bool ValidateRequest (Ydb::StatusIds::StatusCode& status, NYql::TIssues& issues) override {
144
169
const auto & request = *GetProtoRequest ();
145
170
if (request.dry_run ()) {
@@ -207,13 +232,137 @@ class TReplaceStorageConfigRequest : public TBSConfigRequestGrpc<TReplaceStorage
207
232
request->allow_unknown_fields () || request->bypass_checks (),
208
233
request->bypass_checks ());
209
234
}
235
+
236
+ private:
237
+ std::optional<TString> DatabaseConfig;
238
+ std::optional<TString> TargetDatabase;
239
+
240
+ void CheckDatabaseAuthorization () {
241
+ const auto & metadata = NYamlConfig::GetDatabaseMetadata (*DatabaseConfig);
242
+
243
+ if (metadata.Database ) {
244
+ TargetDatabase = metadata.Database ;
245
+ }
246
+ else {
247
+ Reply (Ydb::StatusIds::BAD_REQUEST, " No database name found in metadata" ,
248
+ NKikimrIssues::TIssuesIds::DEFAULT_ERROR, ActorContext ());
249
+ return ;
250
+ }
251
+
252
+ if (*TargetDatabase == (" /" + AppData ()->DomainsInfo ->Domain ->Name ) ||
253
+ *TargetDatabase == AppData ()->DomainsInfo ->Domain ->Name ) {
254
+ Reply (Ydb::StatusIds::BAD_REQUEST, " Provided database is a domain database." ,
255
+ NKikimrIssues::TIssuesIds::DEFAULT_ERROR, ActorContext ());
256
+ return ;
257
+ }
258
+ bool isAdministrator = NKikimr::IsAdministrator (AppData (), Request_->GetSerializedToken ());
259
+ if (!isAdministrator) {
260
+ auto request = std::make_unique<NSchemeCache::TSchemeCacheNavigate>();
261
+ request->DatabaseName = *TargetDatabase;
262
+
263
+ auto & entry = request->ResultSet .emplace_back ();
264
+ entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpPath;
265
+ entry.Path = NKikimr::SplitPath (*TargetDatabase);
266
+
267
+ auto * self = Self ();
268
+ self->Send (MakeSchemeCacheID (), new TEvTxProxySchemeCache::TEvNavigateKeySet (request.release ()));
269
+ self->Become (&TReplaceStorageConfigRequest::StateWaitResolveDatabase);
270
+ return ;
271
+ }
272
+ SendRequestToConsole ();
273
+ }
274
+
275
+ void SendRequestToConsole () {
276
+ NTabletPipe::TClientConfig pipeConfig;
277
+ pipeConfig.RetryPolicy = {
278
+ .RetryLimitCount = 10 ,
279
+ };
280
+ auto pipe = NTabletPipe::CreateClient (SelfId (), MakeConsoleID (), pipeConfig);
281
+ ConsolePipe = RegisterWithSameMailbox (pipe);
282
+
283
+ auto PrepareAndSendRequest = [&](auto requestType) {
284
+ using TRequestType = decltype (requestType);
285
+ auto request = std::make_unique<TRequestType>();
286
+ request->Record .SetUserToken (Request_->GetSerializedToken ());
287
+ request->Record .SetPeerName (Request_->GetPeerName ());
288
+ request->Record .SetIngressDatabase (*TargetDatabase);
289
+
290
+ auto & req = *request->Record .MutableRequest ();
291
+ req.set_config (*DatabaseConfig);
292
+
293
+ request->Record .SetBypassAuth (true );
294
+ NTabletPipe::SendData (SelfId (), ConsolePipe, request.release ());
295
+ };
296
+
297
+ if (GetProtoRequest ()->bypass_checks ()) {
298
+ PrepareAndSendRequest (NConsole::TEvConsole::TEvSetYamlConfigRequest ());
299
+ } else {
300
+ PrepareAndSendRequest (NConsole::TEvConsole::TEvReplaceYamlConfigRequest ());
301
+ }
302
+ Self ()->Become (&TReplaceStorageConfigRequest::StateConsoleReplaceFunc);
303
+ }
304
+
305
+ STFUNC (StateWaitResolveDatabase) {
306
+ switch (ev->GetTypeRewrite ()) {
307
+ hFunc (TEvTxProxySchemeCache::TEvNavigateKeySetResult, HandleResolveDatabase);
308
+ default :
309
+ return TBase::StateFuncBase (ev);
310
+ }
311
+ }
312
+
313
+ void HandleResolveDatabase (TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) {
314
+ const NSchemeCache::TSchemeCacheNavigate& request = *ev->Get ()->Request .Get ();
315
+ auto *self = Self ();
316
+ if (request.ResultSet .empty () || request.ErrorCount > 0 ) {
317
+ self->Reply (Ydb::StatusIds::SCHEME_ERROR, " Error resolving database" ,
318
+ NKikimrIssues::TIssuesIds::GENERIC_RESOLVE_ERROR, self->ActorContext ());
319
+ return ;
320
+ }
321
+
322
+ const auto & entry = request.ResultSet .front ();
323
+ const auto & databaseOwner = entry.Self ->Info .GetOwner ();
324
+
325
+ NACLibProto::TUserToken tokenPb;
326
+ if (!tokenPb.ParseFromString (Request_->GetSerializedToken ())) {
327
+ tokenPb = NACLibProto::TUserToken ();
328
+ }
329
+ const auto & parsedToken = NACLib::TUserToken (tokenPb);
330
+
331
+ bool isDatabaseAdmin = NKikimr::IsDatabaseAdministrator (&parsedToken, databaseOwner);
332
+ if (!isDatabaseAdmin) {
333
+ self->Reply (Ydb::StatusIds::UNAUTHORIZED, " User is not a database administrator." ,
334
+ NKikimrIssues::TIssuesIds::ACCESS_DENIED, self->ActorContext ());
335
+ return ;
336
+ }
337
+ SendRequestToConsole ();
338
+ }
339
+
340
+ STFUNC (StateConsoleReplaceFunc) {
341
+ switch (ev->GetTypeRewrite ()) {
342
+ hFunc (NConsole::TEvConsole::TEvReplaceYamlConfigResponse, Handle);
343
+ hFunc (NConsole::TEvConsole::TEvSetYamlConfigResponse, Handle);
344
+ default :
345
+ return StateConsoleFunc (ev);
346
+ }
347
+ }
348
+
349
+ void Handle (NConsole::TEvConsole::TEvReplaceYamlConfigResponse::TPtr& ev) {
350
+ auto * self = Self ();
351
+ self->Reply (Ydb::StatusIds::SUCCESS, ev->Get ()->Record .GetIssues (), self->ActorContext ());
352
+ }
353
+
354
+ void Handle (NConsole::TEvConsole::TEvSetYamlConfigResponse::TPtr& ev) {
355
+ auto * self = Self ();
356
+ self->Reply (Ydb::StatusIds::SUCCESS, ev->Get ()->Record .GetIssues (), self->ActorContext ());
357
+ }
210
358
};
211
359
212
360
class TFetchStorageConfigRequest : public TBSConfigRequestGrpc <TFetchStorageConfigRequest, TEvFetchStorageConfigRequest,
213
361
Ydb::Config::FetchConfigResult> {
214
362
public:
215
363
using TBase = TBSConfigRequestGrpc<TFetchStorageConfigRequest, TEvFetchStorageConfigRequest, Ydb::Config::FetchConfigResult>;
216
364
using TBase::TBase;
365
+ using TRpcBase = TRpcOperationRequestActor<TFetchStorageConfigRequest, TEvFetchStorageConfigRequest>;
217
366
218
367
bool ValidateRequest (Ydb::StatusIds::StatusCode& status, NYql::TIssues& issues) override {
219
368
const auto & request = *GetProtoRequest ();
@@ -229,6 +378,20 @@ class TFetchStorageConfigRequest : public TBSConfigRequestGrpc<TFetchStorageConf
229
378
return NACLib::GenericManage;
230
379
}
231
380
381
+ void Bootstrap (const TActorContext &ctx) {
382
+ TRpcBase::Bootstrap (ctx);
383
+ auto *self = Self ();
384
+ self->OnBootstrap ();
385
+
386
+ if (self->Request_ ->GetDatabaseName ()) {
387
+ SendRequestToConsole ();
388
+ return ;
389
+ }
390
+
391
+ self->Become (&TFetchStorageConfigRequest::StateFunc);
392
+ self->Send (MakeBlobStorageNodeWardenID (ctx.SelfID .NodeId ()), new TEvNodeWardenQueryStorageConfig (false ));
393
+ }
394
+
232
395
void FillDistconfQuery (NStorage::TEvNodeConfigInvokeOnRoot& ev) const {
233
396
auto *record = ev.Record .MutableFetchStorageConfig ();
234
397
@@ -300,6 +463,39 @@ class TFetchStorageConfigRequest : public TBSConfigRequestGrpc<TFetchStorageConf
300
463
301
464
return ev;
302
465
}
466
+
467
+ private:
468
+ void SendRequestToConsole () {
469
+ NTabletPipe::TClientConfig pipeConfig;
470
+ pipeConfig.RetryPolicy = {
471
+ .RetryLimitCount = 10 ,
472
+ };
473
+ auto pipe = NTabletPipe::CreateClient (SelfId (), MakeConsoleID (), pipeConfig);
474
+ ConsolePipe = RegisterWithSameMailbox (pipe);
475
+
476
+ auto request = std::make_unique<NConsole::TEvConsole::TEvGetAllConfigsRequest>();
477
+ request->Record .SetUserToken (Request_->GetSerializedToken ());
478
+ request->Record .SetPeerName (Request_->GetPeerName ());
479
+ if (Request_->GetDatabaseName ()) {
480
+ request->Record .SetIngressDatabase (*Request_->GetDatabaseName ());
481
+ }
482
+ request->Record .SetBypassAuth (true );
483
+
484
+ NTabletPipe::SendData (SelfId (), ConsolePipe, request.release ());
485
+ Self ()->Become (&TFetchStorageConfigRequest::StateConsoleFetchFunc);
486
+ }
487
+
488
+ STFUNC (StateConsoleFetchFunc) {
489
+ switch (ev->GetTypeRewrite ()) {
490
+ hFunc (NConsole::TEvConsole::TEvGetAllConfigsResponse, Handle);
491
+ default :
492
+ return StateConsoleFunc (ev);
493
+ }
494
+ }
495
+
496
+ void Handle (NConsole::TEvConsole::TEvGetAllConfigsResponse::TPtr& ev) {
497
+ ReplyWithResult (Ydb::StatusIds::SUCCESS, ev->Get ()->Record .GetResponse (), ActorContext ());
498
+ }
303
499
};
304
500
305
501
void DoReplaceConfig (std::unique_ptr<IRequestOpCtx> p, const IFacilityProvider&) {
@@ -372,3 +568,4 @@ void DoBootstrapCluster(std::unique_ptr<IRequestOpCtx> p, const IFacilityProvide
372
568
}
373
569
374
570
} // namespace NKikimr::NGRpcService
571
+
0 commit comments