diff options
author | Alexey Efimov <xeno@prnwatch.com> | 2022-06-06 16:47:14 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-06-06 16:47:14 +0300 |
commit | 9a90a0b585f215a1ac2e35c8fb28258eb24416f7 (patch) | |
tree | fcbdbde73e55e3a791b3e5fda21da499595ddbf1 | |
parent | 53ff143b6db6dffa52da9b82f7e62e17d68ee1e7 (diff) | |
download | ydb-9a90a0b585f215a1ac2e35c8fb28258eb24416f7.tar.gz |
add simple acl handler instead of heavy metainfo KIKIMR-1504122.2.38
REVIEW: 2613565
x-ydb-stable-ref: b87970e132a0056ef96d67b322d37499fe654394
-rw-r--r-- | ydb/core/viewer/json_acl.h | 213 | ||||
-rw-r--r-- | ydb/core/viewer/viewer.cpp | 2 | ||||
-rw-r--r-- | ydb/core/viewer/ya.make | 1 |
3 files changed, 216 insertions, 0 deletions
diff --git a/ydb/core/viewer/json_acl.h b/ydb/core/viewer/json_acl.h new file mode 100644 index 0000000000..43034830fc --- /dev/null +++ b/ydb/core/viewer/json_acl.h @@ -0,0 +1,213 @@ +#pragma once +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <library/cpp/actors/core/mon.h> +#include <ydb/core/base/tablet_pipe.h> +#include <ydb/core/protos/services.pb.h> +#include <ydb/core/tx/schemeshard/schemeshard.h> +#include <ydb/core/tx/tx_proxy/proxy.h> +#include "viewer.h" +#include "json_pipe_req.h" + +namespace NKikimr { +namespace NViewer { + +using namespace NActors; +using NSchemeShard::TEvSchemeShard; + +class TJsonACL : public TViewerPipeClient<TJsonACL> { + using TBase = TViewerPipeClient<TJsonACL>; + IViewer* Viewer; + NMon::TEvHttpInfo::TPtr Event; + TAutoPtr<TEvSchemeShard::TEvDescribeSchemeResult> DescribeResult; + TJsonSettings JsonSettings; + ui32 Timeout = 0; + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { + return NKikimrServices::TActivity::VIEWER_HANDLER; + } + + TJsonACL(IViewer* viewer, NMon::TEvHttpInfo::TPtr &ev) + : Viewer(viewer) + , Event(ev) + {} + + void FillParams(NKikimrSchemeOp::TDescribePath* record, const TCgiParameters& params) { + if (params.Has("path")) { + record->SetPath(params.Get("path")); + } + if (params.Has("path_id")) { + record->SetPathId(FromStringWithDefault<ui64>(params.Get("path_id"))); + } + if (params.Has("schemeshard_id")) { + record->SetSchemeshardId(FromStringWithDefault<ui64>(params.Get("schemeshard_id"))); + } + } + + void Bootstrap() { + const auto& params(Event->Get()->Request.GetParams()); + JsonSettings.EnumAsNumbers = !FromStringWithDefault<bool>(params.Get("enums"), false); + JsonSettings.UI64AsString = !FromStringWithDefault<bool>(params.Get("ui64"), false); + Timeout = FromStringWithDefault<ui32>(params.Get("timeout"), 10000); + InitConfig(params); + + if (params.Has("schemeshard_id")) { + THolder<TEvSchemeShard::TEvDescribeScheme> request = MakeHolder<TEvSchemeShard::TEvDescribeScheme>(); + FillParams(&request->Record, params); + ui64 schemeShardId = FromStringWithDefault<ui64>(params.Get("schemeshard_id")); + SendRequestToPipe(ConnectTabletPipe(schemeShardId), request.Release()); + } else { + THolder<TEvTxUserProxy::TEvNavigate> request = MakeHolder<TEvTxUserProxy::TEvNavigate>(); + FillParams(request->Record.MutableDescribePath(), params); + request->Record.SetUserToken(Event->Get()->UserToken); + SendRequest(MakeTxProxyID(), request.Release()); + } + Become(&TThis::StateRequestedDescribe, TDuration::MilliSeconds(Timeout), new TEvents::TEvWakeup()); + } + + STATEFN(StateRequestedDescribe) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvSchemeShard::TEvDescribeSchemeResult, Handle); + hFunc(TEvTabletPipe::TEvClientConnected, TBase::Handle); + cFunc(TEvents::TSystem::Wakeup, HandleTimeout); + } + } + + void Handle(TEvSchemeShard::TEvDescribeSchemeResult::TPtr& ev) { + DescribeResult = ev->Release(); + RequestDone(); + } + + void ReplyAndPassAway() { + TStringStream json; + TString headers = Viewer->GetHTTPOKJSON(Event->Get()); + if (DescribeResult != nullptr) { + //TProtoToJson::ProtoToJson(json, DescribeResult->GetRecord(), JsonSettings); + const auto& pbRecord(DescribeResult->GetRecord()); + NKikimrViewer::TMetaInfo metaInfo; + NKikimrViewer::TMetaCommonInfo& pbCommon = *metaInfo.MutableCommon(); + pbCommon.SetPath(pbRecord.GetPath()); + if (pbRecord.HasPathDescription()) { + const auto& pbPathDescription(pbRecord.GetPathDescription()); + if (pbPathDescription.HasSelf()) { + const auto& pbSelf(pbPathDescription.GetSelf()); + pbCommon.SetOwner(pbSelf.GetOwner()); + } + if (pbPathDescription.GetSelf().HasACL()) { + NACLib::TACL acl(pbPathDescription.GetSelf().GetACL()); + auto& aces(acl.GetACE()); + for (auto it = aces.begin(); it != aces.end(); ++it) { + const NACLibProto::TACE& ace = *it; + auto& pbAce = *pbCommon.AddACL(); + if (static_cast<NACLib::EAccessType>(ace.GetAccessType()) == NACLib::EAccessType::Deny) { + pbAce.SetAccessType("Deny"); + } else + if (static_cast<NACLib::EAccessType>(ace.GetAccessType()) == NACLib::EAccessType::Allow) { + pbAce.SetAccessType("Allow"); + } + static std::unordered_map<ui32, TString> mapAccessRights = { + {NACLib::EAccessRights::SelectRow, "SelectRow"}, + {NACLib::EAccessRights::UpdateRow, "UpdateRow"}, + {NACLib::EAccessRights::EraseRow, "EraseRow"}, + {NACLib::EAccessRights::ReadAttributes, "ReadAttributes"}, + {NACLib::EAccessRights::WriteAttributes, "WriteAttributes"}, + {NACLib::EAccessRights::CreateDirectory, "CreateDirectory"}, + {NACLib::EAccessRights::CreateTable, "CreateTable"}, + {NACLib::EAccessRights::CreateQueue, "CreateQueue"}, + {NACLib::EAccessRights::RemoveSchema, "RemoveSchema"}, + {NACLib::EAccessRights::DescribeSchema, "DescribeSchema"}, + {NACLib::EAccessRights::AlterSchema, "AlterSchema"}, + {NACLib::EAccessRights::CreateDatabase, "CreateDatabase"}, + {NACLib::EAccessRights::DropDatabase, "DropDatabase"}, + {NACLib::EAccessRights::GrantAccessRights, "GrantAccessRights"}, + {NACLib::EAccessRights::WriteUserAttributes, "WriteUserAttributes"}, + {NACLib::EAccessRights::ConnectDatabase, "ConnectDatabase"}, + {NACLib::EAccessRights::ReadStream, "ReadStream"}, + {NACLib::EAccessRights::WriteStream, "WriteStream"}, + {NACLib::EAccessRights::ReadTopic, "ReadTopic"}, + {NACLib::EAccessRights::WritTopic, "WriteTopic"} + }; + auto ar = ace.GetAccessRight(); + int shift = 0; + while (ar > 0) { + if (ar & (1 << shift)) { + pbAce.AddAccessRights(mapAccessRights[1 << shift]); + ar ^= 1 << shift; + } + ++shift; + } + pbAce.SetSubject(ace.GetSID()); + auto inht = ace.GetInheritanceType(); + if ((inht & NACLib::EInheritanceType::InheritObject) != 0) { + pbAce.AddInheritanceType("InheritObject"); + } + if ((inht & NACLib::EInheritanceType::InheritContainer) != 0) { + pbAce.AddInheritanceType("InheritContainer"); + } + if ((inht & NACLib::EInheritanceType::InheritOnly) != 0) { + pbAce.AddInheritanceType("InheritOnly"); + } + } + } + } + + TProtoToJson::ProtoToJson(json, metaInfo, JsonSettings); + + switch (DescribeResult->GetRecord().GetStatus()) { + case NKikimrScheme::StatusAccessDenied: + headers = HTTPFORBIDDENJSON; + break; + default: + break; + } + } else { + json << "null"; + } + + Send(Event->Sender, new NMon::TEvHttpInfoRes(headers + json.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + PassAway(); + } + + void HandleTimeout() { + Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPGATEWAYTIMEOUT(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + PassAway(); + } +}; + +template <> +struct TJsonRequestSchema<TJsonACL> { + static TString GetSchema() { + TStringStream stream; + TProtoToJson::ProtoToJsonSchema<NKikimrViewer::TMetaInfo>(stream); + return stream.Str(); + } +}; + +template <> +struct TJsonRequestParameters<TJsonACL> { + static TString GetParameters() { + return R"___([{"name":"path","in":"query","description":"schema path","required":false,"type":"string"}, + {"name":"schemeshard_id","in":"query","description":"schemeshard identifier (tablet id)","required":false,"type":"integer"}, + {"name":"path_id","in":"query","description":"path id","required":false,"type":"integer"}, + {"name":"enums","in":"query","description":"convert enums to strings","required":false,"type":"boolean"}, + {"name":"ui64","in":"query","description":"return ui64 as number","required":false,"type":"boolean"}, + {"name":"timeout","in":"query","description":"timeout in ms","required":false,"type":"integer"}])___"; + } +}; + +template <> +struct TJsonRequestSummary<TJsonACL> { + static TString GetSummary() { + return "\"ACL information\""; + } +}; + +template <> +struct TJsonRequestDescription<TJsonACL> { + static TString GetDescription() { + return "\"Returns information about acl of an object\""; + } +}; + +} +} diff --git a/ydb/core/viewer/viewer.cpp b/ydb/core/viewer/viewer.cpp index 6aff691c0a..99c5442787 100644 --- a/ydb/core/viewer/viewer.cpp +++ b/ydb/core/viewer/viewer.cpp @@ -48,6 +48,7 @@ #include "counters_hosts.h" #include "json_healthcheck.h" #include "json_nodes.h" +#include "json_acl.h" namespace NKikimr { namespace NViewer { @@ -208,6 +209,7 @@ public: JsonHandlers["/json/compute"] = new TJsonHandler<TJsonCompute>; JsonHandlers["/json/healthcheck"] = new TJsonHandler<TJsonHealthCheck>; JsonHandlers["/json/nodes"] = new TJsonHandler<TJsonNodes>; + JsonHandlers["/json/acl"] = new TJsonHandler<TJsonACL>; } } diff --git a/ydb/core/viewer/ya.make b/ydb/core/viewer/ya.make index 8ebde73686..b57132547f 100644 --- a/ydb/core/viewer/ya.make +++ b/ydb/core/viewer/ya.make @@ -14,6 +14,7 @@ SRCS( browse_pq.h browse.h counters_hosts.h + json_acl.h json_browse.h json_bscontrollerinfo.h json_bsgroupinfo.h |