aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkungurtsev <kungasc@ydb.tech>2024-12-31 11:51:53 +0100
committerGitHub <noreply@github.com>2024-12-31 11:51:53 +0100
commitbafd5812353f1c4f6ef5ab41b069d3eb765f1b31 (patch)
tree17f9982f3781c234fa659d968f9c76c79f200eef
parent03cfdfdd06771fa6b8e70a28e32b73317d3517f6 (diff)
downloadydb-bafd5812353f1c4f6ef5ab41b069d3eb765f1b31.tar.gz
SystemView Auth Users, Groups, Members (#12521)
-rw-r--r--ydb/core/kqp/ut/common/kqp_ut_common.cpp2
-rw-r--r--ydb/core/sys_view/auth/auth_scan_base.h121
-rw-r--r--ydb/core/sys_view/auth/group_members.cpp70
-rw-r--r--ydb/core/sys_view/auth/group_members.h13
-rw-r--r--ydb/core/sys_view/auth/groups.cpp65
-rw-r--r--ydb/core/sys_view/auth/groups.h13
-rw-r--r--ydb/core/sys_view/auth/users.cpp65
-rw-r--r--ydb/core/sys_view/auth/users.h13
-rw-r--r--ydb/core/sys_view/auth/ya.make21
-rw-r--r--ydb/core/sys_view/common/processor_scan.h5
-rw-r--r--ydb/core/sys_view/common/scan_actor_base_impl.h16
-rw-r--r--ydb/core/sys_view/common/schema.cpp7
-rw-r--r--ydb/core/sys_view/common/schema.h34
-rw-r--r--ydb/core/sys_view/query_stats/query_stats.cpp8
-rw-r--r--ydb/core/sys_view/scan.cpp19
-rw-r--r--ydb/core/sys_view/storage/base.h7
-rw-r--r--ydb/core/sys_view/tablets/tablets.cpp9
-rw-r--r--ydb/core/sys_view/ut_kqp.cpp196
-rw-r--r--ydb/core/sys_view/ya.make2
-rw-r--r--ydb/core/testlib/test_client.cpp51
-rw-r--r--ydb/core/testlib/test_client.h6
-rw-r--r--ydb/core/tx/scheme_cache/scheme_cache.cpp50
-rw-r--r--ydb/core/tx/scheme_cache/scheme_cache.h33
23 files changed, 792 insertions, 34 deletions
diff --git a/ydb/core/kqp/ut/common/kqp_ut_common.cpp b/ydb/core/kqp/ut/common/kqp_ut_common.cpp
index 269570e7ca..ed075e40b1 100644
--- a/ydb/core/kqp/ut/common/kqp_ut_common.cpp
+++ b/ydb/core/kqp/ut/common/kqp_ut_common.cpp
@@ -553,7 +553,7 @@ TString ReformatYson(const TString& yson) {
}
void CompareYson(const TString& expected, const TString& actual) {
- UNIT_ASSERT_NO_DIFF(ReformatYson(expected), ReformatYson(actual));
+ UNIT_ASSERT_VALUES_EQUAL(ReformatYson(expected), ReformatYson(actual));
}
void CompareYson(const TString& expected, const NKikimrMiniKQL::TResult& actual) {
diff --git a/ydb/core/sys_view/auth/auth_scan_base.h b/ydb/core/sys_view/auth/auth_scan_base.h
new file mode 100644
index 0000000000..4a1ef6b25b
--- /dev/null
+++ b/ydb/core/sys_view/auth/auth_scan_base.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include <ydb/core/sys_view/common/events.h>
+#include <ydb/core/sys_view/common/schema.h>
+#include <ydb/core/sys_view/common/scan_actor_base_impl.h>
+#include <ydb/core/base/tablet_pipecache.h>
+#include <ydb/library/login/protos/login.pb.h>
+
+#include <ydb/library/actors/core/hfunc.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+using namespace NSchemeShard;
+using namespace NActors;
+using namespace NSchemeCache;
+using TNavigate = NSchemeCache::TSchemeCacheNavigate;
+
+template <typename TDerived>
+class TAuthScanBase : public TScanActorBase<TDerived> {
+public:
+ using TBase = TScanActorBase<TDerived>;
+
+ static constexpr auto ActorActivityType() {
+ return NKikimrServices::TActivity::KQP_SYSTEM_VIEW_SCAN;
+ }
+
+ TAuthScanBase(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+ : TBase(ownerId, scanId, tableId, tableRange, columns)
+ {
+ }
+
+ STFUNC(StateScan) {
+ switch (ev->GetTypeRewrite()) {
+ hFunc(NKqp::TEvKqpCompute::TEvScanDataAck, Handle);
+ hFunc(TEvPipeCache::TEvDeliveryProblem, Handle);
+ HFunc(TEvTxProxySchemeCache::TEvNavigateKeySetResult, Handle);
+ hFunc(NKqp::TEvKqp::TEvAbortExecution, TBase::HandleAbortExecution);
+ cFunc(TEvents::TEvWakeup::EventType, TBase::HandleTimeout);
+ cFunc(TEvents::TEvPoison::EventType, PassAway);
+ default:
+ LOG_CRIT(*TlsActivationContext, NKikimrServices::SYSTEM_VIEWS,
+ "NSysView::NAuth::TAuthScanBase: unexpected event 0x%08" PRIx32, ev->GetTypeRewrite());
+ }
+ }
+
+protected:
+ void ProceedToScan() override {
+ TBase::Become(&TAuthScanBase::StateScan);
+ if (TBase::AckReceived) {
+ StartScan();
+ }
+ }
+
+ void Handle(NKqp::TEvKqpCompute::TEvScanDataAck::TPtr&) {
+ StartScan();
+ }
+
+ void StartScan() {
+ // TODO: support TableRange filter
+ if (auto cellsFrom = TBase::TableRange.From.GetCells(); cellsFrom.size() > 0 && !cellsFrom[0].IsNull()) {
+ TBase::ReplyErrorAndDie(Ydb::StatusIds::INTERNAL_ERROR, TStringBuilder() << "TableRange.From filter is not supported");
+ return;
+ }
+ if (auto cellsTo = TBase::TableRange.To.GetCells(); cellsTo.size() > 0 && !cellsTo[0].IsNull()) {
+ TBase::ReplyErrorAndDie(Ydb::StatusIds::INTERNAL_ERROR, TStringBuilder() << "TableRange.To filter is not supported");
+ return;
+ }
+
+ NavigatePath(TBase::TenantName);
+ }
+
+ void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev, const TActorContext& ctx) {
+ THolder<NSchemeCache::TSchemeCacheNavigate> request(ev->Get()->Request.Release());
+
+ for (const auto& entry : request->ResultSet) {
+ if (entry.Status != TNavigate::EStatus::Ok) {
+ TBase::ReplyErrorAndDie(Ydb::StatusIds::INTERNAL_ERROR, TStringBuilder() <<
+ "Failed to navigate " << CanonizePath(entry.Path) << ": " << entry.Status);
+ return;
+ }
+ }
+
+ LOG_TRACE_S(ctx, NKikimrServices::SYSTEM_VIEWS,
+ "Got navigate: " << request->ToString(*AppData()->TypeRegistry));
+
+ auto batch = MakeHolder<NKqp::TEvKqpCompute::TEvScanData>(TBase::ScanId);
+
+ FillBatch(*batch, request->ResultSet);
+
+ TBase::SendBatch(std::move(batch));
+ }
+
+ void Handle(TEvPipeCache::TEvDeliveryProblem::TPtr&) {
+ TBase::ReplyErrorAndDie(Ydb::StatusIds::UNAVAILABLE, "Failed to request path info");
+ }
+
+ void PassAway() override {
+ TBase::PassAway();
+ }
+
+ void NavigatePath(TString path) {
+ auto request = MakeHolder<NSchemeCache::TSchemeCacheNavigate>();
+
+ auto& entry = request->ResultSet.emplace_back();
+ entry.RequestType = TSchemeCacheNavigate::TEntry::ERequestType::ByPath;
+ entry.Path = SplitPath(path);
+ entry.Operation = TSchemeCacheNavigate::OpPath;
+ entry.RedirectRequired = false;
+
+ LOG_TRACE_S(TlsActivationContext->AsActorContext(), NKikimrServices::SYSTEM_VIEWS,
+ "Navigate " << path << ": " << request->ToString(*AppData()->TypeRegistry));
+
+ TBase::Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvNavigateKeySet(request.Release()));
+ }
+
+ virtual void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const TNavigate::TResultSet& resultSet) = 0;
+
+};
+
+}
diff --git a/ydb/core/sys_view/auth/group_members.cpp b/ydb/core/sys_view/auth/group_members.cpp
new file mode 100644
index 0000000000..0d9a8cdf29
--- /dev/null
+++ b/ydb/core/sys_view/auth/group_members.cpp
@@ -0,0 +1,70 @@
+#include "auth_scan_base.h"
+#include "group_members.h"
+
+#include <ydb/core/sys_view/common/events.h>
+#include <ydb/core/sys_view/common/schema.h>
+#include <ydb/core/sys_view/common/scan_actor_base_impl.h>
+#include <ydb/core/base/tablet_pipecache.h>
+#include <ydb/library/login/protos/login.pb.h>
+
+#include <ydb/library/actors/core/hfunc.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+using namespace NSchemeShard;
+using namespace NActors;
+
+class TGroupMembersScan : public TAuthScanBase<TGroupMembersScan> {
+public:
+ using TScanBase = TScanActorBase<TGroupMembersScan>;
+ using TAuthBase = TAuthScanBase<TGroupMembersScan>;
+
+ TGroupMembersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+ : TAuthBase(ownerId, scanId, tableId, tableRange, columns)
+ {
+ }
+
+protected:
+ void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const TNavigate::TResultSet& resultSet) override {
+ Y_ABORT_UNLESS(resultSet.size() == 1);
+ auto& entry = resultSet.back();
+ Y_ABORT_UNLESS(entry.Status == TNavigate::EStatus::Ok);
+ Y_ABORT_UNLESS(CanonizePath(entry.Path) == TBase::TenantName);
+
+ TVector<TCell> cells(::Reserve(Columns.size()));
+
+ // TODO: add rows according to request's sender user rights
+
+ for (const auto& group : entry.DomainInfo->Groups) {
+ for (const auto& member : group.Members) {
+ for (auto& column : Columns) {
+ switch (column.Tag) {
+ case Schema::AuthGroupMembers::GroupSid::ColumnId:
+ cells.push_back(TCell(group.Sid.data(), group.Sid.size()));
+ break;
+ case Schema::AuthGroupMembers::MemberSid::ColumnId:
+ cells.push_back(TCell(member.data(), member.size()));
+ break;
+ default:
+ cells.emplace_back();
+ }
+ }
+
+ TArrayRef<const TCell> ref(cells);
+ batch.Rows.emplace_back(TOwnedCellVec::Make(ref));
+ cells.clear();
+ }
+ }
+
+ batch.Finished = true;
+ }
+};
+
+THolder<NActors::IActor> CreateGroupMembersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+{
+ return MakeHolder<TGroupMembersScan>(ownerId, scanId, tableId, tableRange, columns);
+}
+
+}
diff --git a/ydb/core/sys_view/auth/group_members.h b/ydb/core/sys_view/auth/group_members.h
new file mode 100644
index 0000000000..183875871e
--- /dev/null
+++ b/ydb/core/sys_view/auth/group_members.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <ydb/core/kqp/runtime/kqp_compute.h>
+
+#include <ydb/library/actors/core/actor.h>
+#include <ydb/library/actors/core/actorid.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+THolder<NActors::IActor> CreateGroupMembersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns);
+
+}
diff --git a/ydb/core/sys_view/auth/groups.cpp b/ydb/core/sys_view/auth/groups.cpp
new file mode 100644
index 0000000000..805318a41b
--- /dev/null
+++ b/ydb/core/sys_view/auth/groups.cpp
@@ -0,0 +1,65 @@
+#include "auth_scan_base.h"
+#include "groups.h"
+
+#include <ydb/core/sys_view/common/events.h>
+#include <ydb/core/sys_view/common/schema.h>
+#include <ydb/core/sys_view/common/scan_actor_base_impl.h>
+#include <ydb/core/base/tablet_pipecache.h>
+#include <ydb/library/login/protos/login.pb.h>
+
+#include <ydb/library/actors/core/hfunc.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+using namespace NSchemeShard;
+using namespace NActors;
+
+class TGroupsScan : public TAuthScanBase<TGroupsScan> {
+public:
+ using TScanBase = TScanActorBase<TGroupsScan>;
+ using TAuthBase = TAuthScanBase<TGroupsScan>;
+
+ TGroupsScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+ : TAuthBase(ownerId, scanId, tableId, tableRange, columns)
+ {
+ }
+
+protected:
+ void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const TNavigate::TResultSet& resultSet) override {
+ Y_ABORT_UNLESS(resultSet.size() == 1);
+ auto& entry = resultSet.back();
+ Y_ABORT_UNLESS(entry.Status == TNavigate::EStatus::Ok);
+ Y_ABORT_UNLESS(CanonizePath(entry.Path) == TBase::TenantName);
+
+ TVector<TCell> cells(::Reserve(Columns.size()));
+
+ // TODO: add rows according to request's sender user rights
+
+ for (const auto& group : entry.DomainInfo->Groups) {
+ for (auto& column : Columns) {
+ switch (column.Tag) {
+ case Schema::AuthGroups::Sid::ColumnId:
+ cells.push_back(TCell(group.Sid.data(), group.Sid.size()));
+ break;
+ default:
+ cells.emplace_back();
+ }
+ }
+
+ TArrayRef<const TCell> ref(cells);
+ batch.Rows.emplace_back(TOwnedCellVec::Make(ref));
+ cells.clear();
+ }
+
+ batch.Finished = true;
+ }
+};
+
+THolder<NActors::IActor> CreateGroupsScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+{
+ return MakeHolder<TGroupsScan>(ownerId, scanId, tableId, tableRange, columns);
+}
+
+}
diff --git a/ydb/core/sys_view/auth/groups.h b/ydb/core/sys_view/auth/groups.h
new file mode 100644
index 0000000000..512785d46a
--- /dev/null
+++ b/ydb/core/sys_view/auth/groups.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <ydb/core/kqp/runtime/kqp_compute.h>
+
+#include <ydb/library/actors/core/actor.h>
+#include <ydb/library/actors/core/actorid.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+THolder<NActors::IActor> CreateGroupsScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns);
+
+}
diff --git a/ydb/core/sys_view/auth/users.cpp b/ydb/core/sys_view/auth/users.cpp
new file mode 100644
index 0000000000..339b07da72
--- /dev/null
+++ b/ydb/core/sys_view/auth/users.cpp
@@ -0,0 +1,65 @@
+#include "auth_scan_base.h"
+#include "users.h"
+
+#include <ydb/core/sys_view/common/events.h>
+#include <ydb/core/sys_view/common/schema.h>
+#include <ydb/core/sys_view/common/scan_actor_base_impl.h>
+#include <ydb/core/base/tablet_pipecache.h>
+#include <ydb/library/login/protos/login.pb.h>
+
+#include <ydb/library/actors/core/hfunc.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+using namespace NSchemeShard;
+using namespace NActors;
+
+class TUsersScan : public TAuthScanBase<TUsersScan> {
+public:
+ using TScanBase = TScanActorBase<TUsersScan>;
+ using TAuthBase = TAuthScanBase<TUsersScan>;
+
+ TUsersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+ : TAuthBase(ownerId, scanId, tableId, tableRange, columns)
+ {
+ }
+
+protected:
+ void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const TNavigate::TResultSet& resultSet) override {
+ Y_ABORT_UNLESS(resultSet.size() == 1);
+ auto& entry = resultSet.back();
+ Y_ABORT_UNLESS(entry.Status == TNavigate::EStatus::Ok);
+ Y_ABORT_UNLESS(CanonizePath(entry.Path) == TBase::TenantName);
+
+ TVector<TCell> cells(::Reserve(Columns.size()));
+
+ // TODO: add rows according to request's sender user rights
+
+ for (const auto& user : entry.DomainInfo->Users) {
+ for (auto& column : Columns) {
+ switch (column.Tag) {
+ case Schema::AuthUsers::Sid::ColumnId:
+ cells.push_back(TCell(user.Sid.data(), user.Sid.size()));
+ break;
+ default:
+ cells.emplace_back();
+ }
+ }
+
+ TArrayRef<const TCell> ref(cells);
+ batch.Rows.emplace_back(TOwnedCellVec::Make(ref));
+ cells.clear();
+ }
+
+ batch.Finished = true;
+ }
+};
+
+THolder<NActors::IActor> CreateUsersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns)
+{
+ return MakeHolder<TUsersScan>(ownerId, scanId, tableId, tableRange, columns);
+}
+
+}
diff --git a/ydb/core/sys_view/auth/users.h b/ydb/core/sys_view/auth/users.h
new file mode 100644
index 0000000000..23ab3d77a6
--- /dev/null
+++ b/ydb/core/sys_view/auth/users.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <ydb/core/kqp/runtime/kqp_compute.h>
+
+#include <ydb/library/actors/core/actor.h>
+#include <ydb/library/actors/core/actorid.h>
+
+namespace NKikimr::NSysView::NAuth {
+
+THolder<NActors::IActor> CreateUsersScan(const NActors::TActorId& ownerId, ui32 scanId, const TTableId& tableId,
+ const TTableRange& tableRange, const TArrayRef<NMiniKQL::TKqpComputeContextBase::TColumn>& columns);
+
+}
diff --git a/ydb/core/sys_view/auth/ya.make b/ydb/core/sys_view/auth/ya.make
new file mode 100644
index 0000000000..72ef7d11f2
--- /dev/null
+++ b/ydb/core/sys_view/auth/ya.make
@@ -0,0 +1,21 @@
+LIBRARY()
+
+SRCS(
+ group_members.h
+ group_members.cpp
+ users.h
+ users.cpp
+ groups.h
+ groups.cpp
+)
+
+PEERDIR(
+ ydb/library/actors/core
+ ydb/core/base
+ ydb/core/kqp/runtime
+ ydb/core/sys_view/common
+)
+
+YQL_LAST_ABI_VERSION()
+
+END()
diff --git a/ydb/core/sys_view/common/processor_scan.h b/ydb/core/sys_view/common/processor_scan.h
index 1d181f0ae1..1bf999029c 100644
--- a/ydb/core/sys_view/common/processor_scan.h
+++ b/ydb/core/sys_view/common/processor_scan.h
@@ -74,9 +74,7 @@ private:
auto req = MakeHolder<TEvRequest>();
req->Record.CopyFrom(Request);
- TBase::Send(MakePipePerNodeCacheID(false),
- new TEvPipeCache::TEvForward(req.Release(), this->SysViewProcessorId, true),
- IEventHandle::FlagTrackDelivery);
+ this->SendThroughPipeCache(req.Release(), this->SysViewProcessorId);
this->BatchRequestInFlight = true;
}
@@ -110,7 +108,6 @@ private:
}
void PassAway() override {
- TBase::Send(MakePipePerNodeCacheID(false), new TEvPipeCache::TEvUnlink(0));
TBase::PassAway();
}
diff --git a/ydb/core/sys_view/common/scan_actor_base_impl.h b/ydb/core/sys_view/common/scan_actor_base_impl.h
index 966e20e039..c126bdbb8b 100644
--- a/ydb/core/sys_view/common/scan_actor_base_impl.h
+++ b/ydb/core/sys_view/common/scan_actor_base_impl.h
@@ -3,6 +3,7 @@
#include "utils.h"
#include <ydb/core/kqp/compute_actor/kqp_compute_events.h>
+#include <ydb/core/kqp/runtime/kqp_compute.h>
#include <ydb/core/tx/scheme_cache/scheme_cache.h>
#include <ydb/core/mind/tenant_node_enumeration.h>
#include <ydb/core/sys_view/service/sysview_service.h>
@@ -51,6 +52,12 @@ public:
}
protected:
+ void SendThroughPipeCache(IEventBase* ev, ui64 tabletId) {
+ DoPipeCacheUnlink = true;
+ TBase::Send(MakePipePerNodeCacheID(false), new TEvPipeCache::TEvForward(ev, tabletId, true),
+ IEventHandle::FlagTrackDelivery);
+ }
+
void SendBatch(THolder<NKqp::TEvKqpCompute::TEvScanData> batch) {
LOG_DEBUG_S(TlsActivationContext->AsActorContext(), NKikimrServices::SYSTEM_VIEWS,
"Sending scan batch, actor: " << TBase::SelfId()
@@ -116,11 +123,11 @@ protected:
ScanLimiter->Dec();
}
- TBase::PassAway();
- }
+ if (std::exchange(DoPipeCacheUnlink, false)) {
+ TBase::Send(MakePipePerNodeCacheID(false), new TEvPipeCache::TEvUnlink(0));
+ }
- ui64 GetBSControllerId() {
- return MakeBSControllerID();
+ TBase::PassAway();
}
template <typename TResponse, typename TEntry, typename TExtractorsMap, bool BatchSupport = false>
@@ -321,6 +328,7 @@ protected:
bool AckReceived = false;
bool BatchRequestInFlight = false;
+ bool DoPipeCacheUnlink = false;
private:
enum EFailState {
diff --git a/ydb/core/sys_view/common/schema.cpp b/ydb/core/sys_view/common/schema.cpp
index 34703a2e64..6355ec528e 100644
--- a/ydb/core/sys_view/common/schema.cpp
+++ b/ydb/core/sys_view/common/schema.cpp
@@ -286,6 +286,13 @@ private:
RegisterSystemView<Schema::TopPartitions>(TopPartitions1HourName);
RegisterPgTablesSystemViews();
+
+ {
+ using namespace NAuth;
+ RegisterSystemView<Schema::AuthUsers>(UsersName);
+ RegisterSystemView<Schema::AuthGroups>(NAuth::GroupsName);
+ RegisterSystemView<Schema::AuthGroupMembers>(GroupMembersName);
+ }
}
private:
diff --git a/ydb/core/sys_view/common/schema.h b/ydb/core/sys_view/common/schema.h
index 4c134ad597..e6592f66be 100644
--- a/ydb/core/sys_view/common/schema.h
+++ b/ydb/core/sys_view/common/schema.h
@@ -49,6 +49,12 @@ constexpr TStringBuf PgTablesName = "pg_tables";
constexpr TStringBuf InformationSchemaTablesName = "tables";
constexpr TStringBuf PgClassName = "pg_class";
+namespace NAuth {
+ constexpr TStringBuf UsersName = "auth_users";
+ constexpr TStringBuf GroupsName = "auth_groups";
+ constexpr TStringBuf GroupMembersName = "auth_group_members";
+}
+
struct Schema : NIceDb::Schema {
struct PartitionStats : Table<1> {
@@ -611,6 +617,34 @@ struct Schema : NIceDb::Schema {
>;
};
+ struct AuthUsers : Table<15> {
+ struct Sid: Column<1, NScheme::NTypeIds::Utf8> {};
+
+ using TKey = TableKey<Sid>;
+ using TColumns = TableColumns<
+ Sid
+ >;
+ };
+
+ struct AuthGroups : Table<16> {
+ struct Sid: Column<1, NScheme::NTypeIds::Utf8> {};
+
+ using TKey = TableKey<Sid>;
+ using TColumns = TableColumns<
+ Sid
+ >;
+ };
+
+ struct AuthGroupMembers : Table<17> {
+ struct GroupSid: Column<1, NScheme::NTypeIds::Utf8> {};
+ struct MemberSid: Column<2, NScheme::NTypeIds::Utf8> {};
+
+ using TKey = TableKey<GroupSid, MemberSid>;
+ using TColumns = TableColumns<
+ GroupSid,
+ MemberSid
+ >;
+ };
struct PgColumn {
NIceDb::TColumnId _ColumnId;
diff --git a/ydb/core/sys_view/query_stats/query_stats.cpp b/ydb/core/sys_view/query_stats/query_stats.cpp
index c2e26a2379..35a24b2d94 100644
--- a/ydb/core/sys_view/query_stats/query_stats.cpp
+++ b/ydb/core/sys_view/query_stats/query_stats.cpp
@@ -172,9 +172,7 @@ private:
auto request = MakeHolder<TEvSysView::TEvGetQueryMetricsRequest>();
request->Record.CopyFrom(Request);
- this->Send(MakePipePerNodeCacheID(false),
- new TEvPipeCache::TEvForward(request.Release(), this->SysViewProcessorId, true),
- IEventHandle::FlagTrackDelivery);
+ this->SendThroughPipeCache(request.Release(), this->SysViewProcessorId);
this->BatchRequestInFlight = true;
}
@@ -468,9 +466,7 @@ private:
}
void PassAway() override {
- if (UseProcessor) {
- this->Send(MakePipePerNodeCacheID(false), new TEvPipeCache::TEvUnlink(0));
- } else {
+ if (!UseProcessor) {
for (auto& [nodeId, _] : Nodes) {
this->Send(TActorContext::InterconnectProxy(nodeId), new TEvents::TEvUnsubscribe);
}
diff --git a/ydb/core/sys_view/scan.cpp b/ydb/core/sys_view/scan.cpp
index 87fb15cd96..763689b4c9 100644
--- a/ydb/core/sys_view/scan.cpp
+++ b/ydb/core/sys_view/scan.cpp
@@ -2,6 +2,9 @@
#include <ydb/core/kqp/compute_actor/kqp_compute_events.h>
+#include <ydb/core/sys_view/auth/users.h>
+#include <ydb/core/sys_view/auth/groups.h>
+#include <ydb/core/sys_view/auth/group_members.h>
#include <ydb/core/sys_view/common/schema.h>
#include <ydb/core/sys_view/partition_stats/partition_stats.h>
#include <ydb/core/sys_view/nodes/nodes.h>
@@ -233,10 +236,24 @@ THolder<NActors::IActor> CreateSystemViewScan(
if (tableId.SysViewInfo == InformationSchemaTablesName) {
return CreateInformationSchemaTablesScan(ownerId, scanId, tableId, tablePath, tableRange, columns);
}
- if (tableId.SysViewInfo == PgClassName) {
+
+ if (tableId.SysViewInfo == PgClassName) {
return CreatePgClassScan(ownerId, scanId, tableId, tablePath, tableRange, columns);
}
+ {
+ using namespace NAuth;
+ if (tableId.SysViewInfo == UsersName) {
+ return CreateUsersScan(ownerId, scanId, tableId, tableRange, columns);
+ }
+ if (tableId.SysViewInfo == NAuth::GroupsName) {
+ return NAuth::CreateGroupsScan(ownerId, scanId, tableId, tableRange, columns);
+ }
+ if (tableId.SysViewInfo == GroupMembersName) {
+ return NAuth::CreateGroupMembersScan(ownerId, scanId, tableId, tableRange, columns);
+ }
+ }
+
return {};
}
diff --git a/ydb/core/sys_view/storage/base.h b/ydb/core/sys_view/storage/base.h
index 65c8aa2910..709be1ae64 100644
--- a/ydb/core/sys_view/storage/base.h
+++ b/ydb/core/sys_view/storage/base.h
@@ -42,14 +42,9 @@ namespace NKikimr::NSysView {
}
void StartScan() {
- ui64 bsControllerId = TBase::GetBSControllerId();
- if (!bsControllerId) {
- return;
- }
-
auto pipeCache = MakePipePerNodeCacheID(false);
TBase::Send(pipeCache, new TEvPipeCache::TEvForward(static_cast<TDerived&>(*this).CreateQuery(),
- bsControllerId, true), IEventHandle::FlagTrackDelivery);
+ MakeBSControllerID(), true), IEventHandle::FlagTrackDelivery);
}
void Handle(NKqp::TEvKqpCompute::TEvScanDataAck::TPtr&) {
diff --git a/ydb/core/sys_view/tablets/tablets.cpp b/ydb/core/sys_view/tablets/tablets.cpp
index ffecd239b1..b976c47399 100644
--- a/ydb/core/sys_view/tablets/tablets.cpp
+++ b/ydb/core/sys_view/tablets/tablets.cpp
@@ -180,9 +180,7 @@ private:
record.SetFrom(FromTabletId);
record.SetTo(ToTabletId);
- auto pipeCache = MakePipePerNodeCacheID(false);
- Send(pipeCache, new TEvPipeCache::TEvForward(request.Release(), HiveId, true),
- IEventHandle::FlagTrackDelivery);
+ SendThroughPipeCache(request.Release(), HiveId);
}
void RequestBatch() {
@@ -202,9 +200,7 @@ private:
record.SetBatchSizeLimit(BatchSize);
- auto pipeCache = MakePipePerNodeCacheID(false);
- Send(pipeCache, new TEvPipeCache::TEvForward(request.Release(), HiveId, true),
- IEventHandle::FlagTrackDelivery);
+ SendThroughPipeCache(request.Release(), HiveId);
}
void Handle(TEvPipeCache::TEvDeliveryProblem::TPtr&) {
@@ -338,7 +334,6 @@ private:
}
void PassAway() override {
- Send(MakePipePerNodeCacheID(false), new TEvPipeCache::TEvUnlink(0));
TBase::PassAway();
}
diff --git a/ydb/core/sys_view/ut_kqp.cpp b/ydb/core/sys_view/ut_kqp.cpp
index 004747b0fd..aa5ba9ff0e 100644
--- a/ydb/core/sys_view/ut_kqp.cpp
+++ b/ydb/core/sys_view/ut_kqp.cpp
@@ -1730,7 +1730,7 @@ Y_UNIT_TEST_SUITE(SystemView) {
UNIT_ASSERT_VALUES_EQUAL(entry.Type, ESchemeEntryType::Directory);
auto children = result.GetChildren();
- UNIT_ASSERT_VALUES_EQUAL(children.size(), 23);
+ UNIT_ASSERT_VALUES_EQUAL(children.size(), 26);
THashSet<TString> names;
for (const auto& child : children) {
@@ -1748,7 +1748,7 @@ Y_UNIT_TEST_SUITE(SystemView) {
UNIT_ASSERT_VALUES_EQUAL(entry.Type, ESchemeEntryType::Directory);
auto children = result.GetChildren();
- UNIT_ASSERT_VALUES_EQUAL(children.size(), 17);
+ UNIT_ASSERT_VALUES_EQUAL(children.size(), 20);
THashSet<TString> names;
for (const auto& child : children) {
@@ -2134,6 +2134,198 @@ Y_UNIT_TEST_SUITE(SystemView) {
[[0u]];
])", ysonString);
}
+
+ Y_UNIT_TEST(AuthUsers) {
+ TTestEnv env;
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_DEBUG);
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::SYSTEM_VIEWS, NLog::PRI_TRACE);
+ CreateTenantsAndTables(env, true);
+ TTableClient client(env.GetDriver());
+
+ env.GetClient().CreateUser("/Root", "user1", "password1");
+ env.GetClient().CreateUser("/Root/Tenant1", "user2", "password2");
+ env.GetClient().CreateUser("/Root/Tenant2", "user3", "password3");
+ env.GetClient().CreateUser("/Root/Tenant2", "user4", "password4");
+ env.GetClient().CreateGroup("/Root", "group1");
+ env.GetClient().CreateGroup("/Root/Tenant1", "group2");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group3");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group4");
+
+ // Cerr << env.GetClient().Describe(env.GetServer().GetRuntime(), "/Root").DebugString() << Endl;
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/.sys/auth_users`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["user1"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant1/.sys/auth_users`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["user2"]]
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant2/.sys/auth_users`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["user4"]];
+ [["user3"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+ }
+
+ Y_UNIT_TEST(AuthGroups) {
+ TTestEnv env;
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_DEBUG);
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::SYSTEM_VIEWS, NLog::PRI_TRACE);
+ CreateTenantsAndTables(env, true);
+ TTableClient client(env.GetDriver());
+
+ env.GetClient().CreateUser("/Root", "user1", "password1");
+ env.GetClient().CreateUser("/Root/Tenant1", "user2", "password2");
+ env.GetClient().CreateUser("/Root/Tenant2", "user3", "password3");
+ env.GetClient().CreateUser("/Root/Tenant2", "user4", "password4");
+ env.GetClient().CreateGroup("/Root", "group1");
+ env.GetClient().CreateGroup("/Root/Tenant1", "group2");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group3");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group4");
+
+ // Cerr << env.GetClient().Describe(env.GetServer().GetRuntime(), "/Root").DebugString() << Endl;
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/.sys/auth_groups`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group1"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant1/.sys/auth_groups`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group2"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant2/.sys/auth_groups`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group4"]];
+ [["group3"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+ }
+
+
+
+ Y_UNIT_TEST(AuthGroupMembers) {
+ TTestEnv env;
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_DEBUG);
+ env.GetServer().GetRuntime()->SetLogPriority(NKikimrServices::SYSTEM_VIEWS, NLog::PRI_TRACE);
+ CreateTenantsAndTables(env, true);
+ TTableClient client(env.GetDriver());
+
+ env.GetClient().CreateUser("/Root", "user1", "password1");
+ env.GetClient().CreateUser("/Root/Tenant1", "user2", "password2");
+ env.GetClient().CreateUser("/Root/Tenant2", "user3", "password3");
+ env.GetClient().CreateUser("/Root/Tenant2", "user4", "password4");
+ env.GetClient().CreateGroup("/Root", "group1");
+ env.GetClient().CreateGroup("/Root/Tenant1", "group2");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group3");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group4");
+ env.GetClient().CreateGroup("/Root/Tenant2", "group5");
+
+ env.GetClient().AddGroupMembership("/Root", "group1", "user1");
+ env.GetClient().AddGroupMembership("/Root/Tenant1", "group2", "user2");
+ env.GetClient().AddGroupMembership("/Root/Tenant2", "group3", "user4");
+ env.GetClient().AddGroupMembership("/Root/Tenant2", "group4", "user3");
+ env.GetClient().AddGroupMembership("/Root/Tenant2", "group4", "user4");
+ env.GetClient().AddGroupMembership("/Root/Tenant2", "group4", "group3");
+ env.GetClient().AddGroupMembership("/Root/Tenant2", "group4", "group4");
+
+ // Cerr << env.GetClient().Describe(env.GetServer().GetRuntime(), "/Root").DebugString() << Endl;
+ // Cerr << env.GetClient().Describe(env.GetServer().GetRuntime(), "/Root/Tenant2").DebugString() << Endl;
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/.sys/auth_group_members`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group1"];["user1"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant1/.sys/auth_group_members`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group2"];["user2"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+
+ {
+ auto it = client.StreamExecuteScanQuery(R"(
+ SELECT *
+ FROM `Root/Tenant2/.sys/auth_group_members`
+ )").GetValueSync();
+
+ auto expected = R"([
+ [["group4"];["group4"]];
+ [["group4"];["group3"]];
+ [["group4"];["user4"]];
+ [["group4"];["user3"]];
+ [["group3"];["user4"]];
+ ])";
+
+ NKqp::CompareYson(expected, NKqp::StreamResultToYson(it));
+ }
+ }
}
} // NSysView
diff --git a/ydb/core/sys_view/ya.make b/ydb/core/sys_view/ya.make
index df596d8438..74bfd9e155 100644
--- a/ydb/core/sys_view/ya.make
+++ b/ydb/core/sys_view/ya.make
@@ -8,6 +8,7 @@ SRCS(
PEERDIR(
ydb/core/base
ydb/core/kqp/runtime
+ ydb/core/sys_view/auth
ydb/core/sys_view/common
ydb/core/sys_view/nodes
ydb/core/sys_view/sessions
@@ -24,6 +25,7 @@ YQL_LAST_ABI_VERSION()
END()
RECURSE(
+ auth
common
nodes
partition_stats
diff --git a/ydb/core/testlib/test_client.cpp b/ydb/core/testlib/test_client.cpp
index 2a22901ee5..ea5b47e416 100644
--- a/ydb/core/testlib/test_client.cpp
+++ b/ydb/core/testlib/test_client.cpp
@@ -1772,6 +1772,39 @@ namespace Tests {
return event->Record;
}
+ NMsgBusProxy::EResponseStatus TClient::CreateGroup(const TString& parent, const TString& group) {
+ TAutoPtr<NMsgBusProxy::TBusSchemeOperation> request(new NMsgBusProxy::TBusSchemeOperation());
+ auto* op = request->Record.MutableTransaction()->MutableModifyScheme();
+ op->SetOperationType(NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin);
+ op->SetWorkingDir(parent);
+
+ auto* createUser = op->MutableAlterLogin()->MutableCreateGroup();
+ createUser->SetGroup(group);
+
+ TAutoPtr<NBus::TBusMessage> reply;
+ NBus::EMessageStatus status = SendAndWaitCompletion(request.Release(), reply);
+ UNIT_ASSERT_VALUES_EQUAL(status, NBus::MESSAGE_OK);
+ const NKikimrClient::TResponse &response = dynamic_cast<NMsgBusProxy::TBusResponse *>(reply.Get())->Record;
+ return (NMsgBusProxy::EResponseStatus)response.GetStatus();
+ }
+
+ NMsgBusProxy::EResponseStatus TClient::AddGroupMembership(const TString& parent, const TString& group, const TString& member) {
+ TAutoPtr<NMsgBusProxy::TBusSchemeOperation> request(new NMsgBusProxy::TBusSchemeOperation());
+ auto* op = request->Record.MutableTransaction()->MutableModifyScheme();
+ op->SetOperationType(NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin);
+ op->SetWorkingDir(parent);
+
+ auto* createUser = op->MutableAlterLogin()->MutableAddGroupMembership();
+ createUser->SetGroup(group);
+ createUser->SetMember(member);
+
+ TAutoPtr<NBus::TBusMessage> reply;
+ NBus::EMessageStatus status = SendAndWaitCompletion(request.Release(), reply);
+ UNIT_ASSERT_VALUES_EQUAL(status, NBus::MESSAGE_OK);
+ const NKikimrClient::TResponse &response = dynamic_cast<NMsgBusProxy::TBusResponse *>(reply.Get())->Record;
+ return (NMsgBusProxy::EResponseStatus)response.GetStatus();
+ }
+
NMsgBusProxy::EResponseStatus TClient::CreateTable(const TString& parent, const NKikimrSchemeOp::TTableDescription &table, TDuration timeout) {
TAutoPtr<NMsgBusProxy::TBusSchemeOperation> request(new NMsgBusProxy::TBusSchemeOperation());
auto *op = request->Record.MutableTransaction()->MutableModifyScheme();
@@ -2221,6 +2254,24 @@ namespace Tests {
return res;
}
+ NKikimrScheme::TEvDescribeSchemeResult TClient::Describe(TTestActorRuntime* runtime, const TString& path, ui64 tabletId) {
+ TAutoPtr<NSchemeShard::TEvSchemeShard::TEvDescribeScheme> request(new NSchemeShard::TEvSchemeShard::TEvDescribeScheme());
+ request->Record.SetPath(path);
+ const ui64 schemeRoot = GetPatchedSchemeRoot(tabletId, Domain, SupportsRedirect);
+ TActorId sender = runtime->AllocateEdgeActor(0);
+ ForwardToTablet(*runtime, schemeRoot, sender, request.Release(), 0);
+
+ TAutoPtr<IEventHandle> handle;
+ runtime->GrabEdgeEvent<NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult>(handle);
+ auto& record = handle->Get<NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult>()->GetRecord();
+
+ if (auto schemeShardId = record.GetPathDescription().GetDomainDescription().GetProcessingParams().GetSchemeShard(); schemeShardId && schemeShardId != tabletId) {
+ return Describe(runtime, path, schemeShardId);
+ } else {
+ return record;
+ }
+ }
+
TString TClient::CreateStoragePool(const TString& poolKind, const TString& partOfName, ui32 groups) {
Y_ABORT_UNLESS(StoragePoolTypes.contains(poolKind));
const TString poolName = Sprintf("name_%s_kind_%s", partOfName.c_str(), poolKind.c_str());
diff --git a/ydb/core/testlib/test_client.h b/ydb/core/testlib/test_client.h
index c6292ed665..75e9486107 100644
--- a/ydb/core/testlib/test_client.h
+++ b/ydb/core/testlib/test_client.h
@@ -6,6 +6,7 @@
#include <ydb/core/base/tablet_types.h>
#include <ydb/core/base/domain.h>
#include <ydb/core/driver_lib/run/config.h>
+#include <ydb/core/tx/schemeshard/schemeshard.h>
#include <ydb/public/api/protos/ydb_cms.pb.h>
#include <ydb/public/sdk/cpp/client/ydb_driver/driver.h>
#include <ydb/public/lib/deprecated/client/msgbus_client.h>
@@ -460,7 +461,9 @@ namespace Tests {
NMsgBusProxy::EResponseStatus CreateUser(const TString& parent, const TString& user, const TString& password, const TString& userToken = "");
NMsgBusProxy::EResponseStatus ModifyUser(const TString& parent, const TString& user, const TString& password, const TString& userToken = "");
NKikimrScheme::TEvLoginResult Login(TTestActorRuntime& runtime, const TString& user, const TString& password);
-
+ NMsgBusProxy::EResponseStatus CreateGroup(const TString& parent, const TString& group);
+ NMsgBusProxy::EResponseStatus AddGroupMembership(const TString& parent, const TString& group, const TString& member);
+
NMsgBusProxy::EResponseStatus CreateTable(const TString& parent, const TString& scheme, TDuration timeout = TDuration::Seconds(5000));
NMsgBusProxy::EResponseStatus CreateTable(const TString& parent, const NKikimrSchemeOp::TTableDescription &table, TDuration timeout = TDuration::Seconds(5000));
NMsgBusProxy::EResponseStatus CreateTableWithUniformShardedIndex(const TString& parent,
@@ -513,6 +516,7 @@ namespace Tests {
void SetSecurityToken(const TString& token) { SecurityToken = token; }
void ModifyOwner(const TString& parent, const TString& name, const TString& owner);
void ModifyACL(const TString& parent, const TString& name, const TString& acl);
+ NKikimrScheme::TEvDescribeSchemeResult Describe(TTestActorRuntime* runtime, const TString& path, ui64 tabletId = SchemeRoot);
TString CreateStoragePool(const TString& poolKind, const TString& partOfName, ui32 groups = 1);
NKikimrBlobStorage::TDefineStoragePool DescribeStoragePool(const TString& name);
void RemoveStoragePool(const TString& name);
diff --git a/ydb/core/tx/scheme_cache/scheme_cache.cpp b/ydb/core/tx/scheme_cache/scheme_cache.cpp
index 67caca5044..8e5a3a367c 100644
--- a/ydb/core/tx/scheme_cache/scheme_cache.cpp
+++ b/ydb/core/tx/scheme_cache/scheme_cache.cpp
@@ -20,14 +20,60 @@ TSchemeCacheConfig::TSchemeCacheConfig(const TAppData* appData, ::NMonitoring::T
}
TString TDomainInfo::ToString() const {
- return TStringBuilder() << "{"
+ auto result = TStringBuilder() << "{"
<< " DomainKey: " << DomainKey
<< " ResourcesDomainKey: " << ResourcesDomainKey
<< " Params { " << Params.ShortDebugString() << " }"
- << " ServerlessComputeResourcesMode: " << ServerlessComputeResourcesMode
+ << " ServerlessComputeResourcesMode: " << ServerlessComputeResourcesMode;
+
+ result << " Users: [";
+ for (ui32 i = 0; i < Users.size(); ++i) {
+ if (i) {
+ result << ",";
+ }
+
+ result << Users.at(i).ToString();
+ }
+ result << "]";
+
+ result << " Groups: [";
+ for (ui32 i = 0; i < Groups.size(); ++i) {
+ if (i) {
+ result << ",";
+ }
+
+ result << Groups.at(i).ToString();
+ }
+ result << "]";
+
+ result << " }";
+ return result;
+}
+
+TString TDomainInfo::TUser::ToString() const {
+ return TStringBuilder() << "{"
+ << " Sid: " << Sid
<< " }";
}
+TString TDomainInfo::TGroup::ToString() const {
+ auto result = TStringBuilder() << "{"
+ << " Sid: " << Sid;
+
+ result << " Members: [";
+ for (ui32 i = 0; i < Members.size(); ++i) {
+ if (i) {
+ result << ",";
+ }
+
+ result << Members.at(i);
+ }
+ result << "]";
+
+ result << " }";
+ return result;
+}
+
TString TSchemeCacheNavigate::TEntry::ToString() const {
return TStringBuilder() << "{"
<< " Path: " << JoinPath(Path)
diff --git a/ydb/core/tx/scheme_cache/scheme_cache.h b/ydb/core/tx/scheme_cache/scheme_cache.h
index 6798bf4164..966a6da936 100644
--- a/ydb/core/tx/scheme_cache/scheme_cache.h
+++ b/ydb/core/tx/scheme_cache/scheme_cache.h
@@ -13,6 +13,7 @@
#include <ydb/core/scheme_types/scheme_type_registry.h>
#include <ydb/core/tx/locks/sys_tables.h>
#include <ydb/library/aclib/aclib.h>
+#include <ydb/library/login/protos/login.pb.h>
#include <util/datetime/base.h>
#include <util/generic/hash.h>
@@ -48,6 +49,19 @@ struct TSchemeCacheConfig : public TThrRefBase {
struct TDomainInfo : public TAtomicRefCount<TDomainInfo> {
using TPtr = TIntrusivePtr<TDomainInfo>;
+ struct TUser {
+ TString Sid;
+
+ TString ToString() const;
+ };
+
+ struct TGroup {
+ TString Sid;
+ TVector<TString> Members;
+
+ TString ToString() const;
+ };
+
explicit TDomainInfo(const TPathId& domainKey, const TPathId& resourcesDomainKey)
: DomainKey(domainKey)
, ResourcesDomainKey(resourcesDomainKey)
@@ -72,6 +86,23 @@ struct TDomainInfo : public TAtomicRefCount<TDomainInfo> {
if (descr.HasSharedHive()) {
SharedHiveId = descr.GetSharedHive();
}
+
+ if (descr.HasSecurityState()) {
+ for (const auto& sid : descr.GetSecurityState().GetSids()) {
+ switch (sid.GetType()) {
+ case NLoginProto::ESidType_SidType_USER:
+ Users.emplace_back(sid.GetName());
+ break;
+ case NLoginProto::ESidType_SidType_GROUP: {
+ TVector<TString> members(sid.GetMembers().begin(), sid.GetMembers().end());
+ Groups.emplace_back(sid.GetName(), std::move(members));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
}
inline ui64 GetVersion() const {
@@ -104,6 +135,8 @@ struct TDomainInfo : public TAtomicRefCount<TDomainInfo> {
TCoordinators Coordinators;
TMaybeServerlessComputeResourcesMode ServerlessComputeResourcesMode;
ui64 SharedHiveId = 0;
+ TVector<TUser> Users;
+ TVector<TGroup> Groups;
TString ToString() const;