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