diff options
| -rw-r--r-- | ydb/core/sys_view/auth/auth_scan_base.h | 21 | ||||
| -rw-r--r-- | ydb/core/sys_view/auth/group_members.cpp | 43 | ||||
| -rw-r--r-- | ydb/core/sys_view/auth/groups.cpp | 12 | ||||
| -rw-r--r-- | ydb/core/sys_view/auth/permissions.cpp | 62 | ||||
| -rw-r--r-- | ydb/core/sys_view/auth/sort_helpers.h | 24 | ||||
| -rw-r--r-- | ydb/core/sys_view/auth/users.cpp | 47 | ||||
| -rw-r--r-- | ydb/core/sys_view/common/schema.h | 2 | ||||
| -rw-r--r-- | ydb/core/sys_view/ut_kqp.cpp | 323 |
8 files changed, 428 insertions, 106 deletions
diff --git a/ydb/core/sys_view/auth/auth_scan_base.h b/ydb/core/sys_view/auth/auth_scan_base.h index efb60aa0b14..a0363601360 100644 --- a/ydb/core/sys_view/auth/auth_scan_base.h +++ b/ydb/core/sys_view/auth/auth_scan_base.h @@ -1,5 +1,7 @@ #pragma once +#include "sort_helpers.h" + #include <ydb/core/base/auth.h> #include <ydb/core/sys_view/common/events.h> #include <ydb/core/sys_view/common/schema.h> @@ -21,7 +23,22 @@ template <typename TDerived> class TAuthScanBase : public TScanActorBase<TDerived> { struct TTraversingChildren { TNavigate::TEntry Entry; + TVector<const TNavigate::TListNodeEntry::TChild*> SortedChildren; size_t Index = 0; + + TTraversingChildren() = default; + + TTraversingChildren(TNavigate::TEntry&& entry) + : Entry(std::move(entry)) + , SortedChildren(::Reserve(Entry.ListNodeEntry->Children.size())) + { + for (const auto& child : Entry.ListNodeEntry->Children) { + SortedChildren.push_back(&child); + } + SortBatch(SortedChildren, [](const auto* left, const auto* right) { + return left->Name < right->Name; + }); + } }; public: @@ -96,9 +113,9 @@ protected: return; } - auto& children = last.Entry.ListNodeEntry->Children; + auto& children = last.SortedChildren; if (last.Index < children.size()) { - auto& child = children.at(last.Index++); + const auto& child = *children.at(last.Index++); if (child.Kind == TSchemeCacheNavigate::KindExtSubdomain || child.Kind == TSchemeCacheNavigate::KindSubdomain) { continue; diff --git a/ydb/core/sys_view/auth/group_members.cpp b/ydb/core/sys_view/auth/group_members.cpp index a8a223e881a..da290a40ec7 100644 --- a/ydb/core/sys_view/auth/group_members.cpp +++ b/ydb/core/sys_view/auth/group_members.cpp @@ -31,27 +31,36 @@ protected: Y_ABORT_UNLESS(entry.Status == TNavigate::EStatus::Ok); Y_ABORT_UNLESS(CanonizePath(entry.Path) == TBase::TenantName); - TVector<TCell> cells(::Reserve(Columns.size())); - + TVector<std::pair<const TDomainInfo::TGroup*, const TString*>> memberships; 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(); - } - } + memberships.emplace_back(&group, &member); + } + } + SortBatch(memberships, [](const auto& left, const auto& right) { + return left.first->Sid < right.first->Sid || + left.first->Sid == right.first->Sid && *left.second < *right.second; + }); - TArrayRef<const TCell> ref(cells); - batch.Rows.emplace_back(TOwnedCellVec::Make(ref)); - cells.clear(); + TVector<TCell> cells(::Reserve(Columns.size())); + + for (const auto& [group, member] : memberships) { + 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; diff --git a/ydb/core/sys_view/auth/groups.cpp b/ydb/core/sys_view/auth/groups.cpp index c7ca81d9c99..d5add729896 100644 --- a/ydb/core/sys_view/auth/groups.cpp +++ b/ydb/core/sys_view/auth/groups.cpp @@ -30,14 +30,22 @@ protected: void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const TNavigate::TEntry& entry) override { Y_ABORT_UNLESS(entry.Status == TNavigate::EStatus::Ok); Y_ABORT_UNLESS(CanonizePath(entry.Path) == TBase::TenantName); + + TVector<const TDomainInfo::TGroup*> groups(::Reserve(entry.DomainInfo->Groups.size())); + for (const auto& group : entry.DomainInfo->Groups) { + groups.push_back(&group); + } + SortBatch(groups, [](const auto* left, const auto* right) { + return left->Sid < right->Sid; + }); TVector<TCell> cells(::Reserve(Columns.size())); - for (const auto& group : entry.DomainInfo->Groups) { + for (const auto* group : groups) { for (auto& column : Columns) { switch (column.Tag) { case Schema::AuthGroups::Sid::ColumnId: - cells.push_back(TCell(group.Sid.data(), group.Sid.size())); + cells.push_back(TCell(group->Sid.data(), group->Sid.size())); break; default: cells.emplace_back(); diff --git a/ydb/core/sys_view/auth/permissions.cpp b/ydb/core/sys_view/auth/permissions.cpp index 11d1066ccb4..30fb45653f6 100644 --- a/ydb/core/sys_view/auth/permissions.cpp +++ b/ydb/core/sys_view/auth/permissions.cpp @@ -37,10 +37,7 @@ protected: return; } - TVector<TCell> cells(::Reserve(Columns.size())); - - auto entryPath = CanonizePath(entry.Path); - + TVector<std::pair<TString, TString>> permissions; for (const NACLibProto::TACE& ace : entry.SecurityObject->GetACL().GetACE()) { if (ace.GetAccessType() != (ui32)NACLib::EAccessType::Allow) { continue; @@ -49,32 +46,45 @@ protected: continue; } - auto permissions = ConvertACLMaskToYdbPermissionNames(ace.GetAccessRight()); - for (const auto& permission : permissions) { - for (auto& column : Columns) { - switch (column.Tag) { - case Schema::AuthPermissions::Path::ColumnId: - cells.push_back(TCell(entryPath.data(), entryPath.size())); - break; - case Schema::AuthPermissions::Sid::ColumnId: - if (ace.HasSID()) { - cells.push_back(TCell(ace.GetSID().data(), ace.GetSID().size())); - } else { - cells.emplace_back(); - } - break; - case Schema::AuthPermissions::Permission::ColumnId: - cells.push_back(TCell(permission.data(), permission.size())); - break; - default: + auto acePermissions = ConvertACLMaskToYdbPermissionNames(ace.GetAccessRight()); + for (const auto& permission : acePermissions) { + permissions.emplace_back(ace.HasSID() ? ace.GetSID() : TString{}, std::move(permission)); + } + } + // Note: due to rights inheritance permissions may be duplicated + SortBatch(permissions, [](const auto& left, const auto& right) { + return left.first < right.first || + left.first == right.first && left.second < right.second; + }, false); + + TVector<TCell> cells(::Reserve(Columns.size())); + + auto entryPath = CanonizePath(entry.Path); + + for (const auto& [sid, permission] : permissions) { + for (auto& column : Columns) { + switch (column.Tag) { + case Schema::AuthPermissions::Path::ColumnId: + cells.push_back(TCell(entryPath.data(), entryPath.size())); + break; + case Schema::AuthPermissions::Sid::ColumnId: + if (sid) { + cells.push_back(TCell(sid.data(), sid.size())); + } else { cells.emplace_back(); } + break; + case Schema::AuthPermissions::Permission::ColumnId: + cells.push_back(TCell(permission.data(), permission.size())); + break; + default: + cells.emplace_back(); } - - TArrayRef<const TCell> ref(cells); - batch.Rows.emplace_back(TOwnedCellVec::Make(ref)); - cells.clear(); } + + TArrayRef<const TCell> ref(cells); + batch.Rows.emplace_back(TOwnedCellVec::Make(ref)); + cells.clear(); } batch.Finished = false; diff --git a/ydb/core/sys_view/auth/sort_helpers.h b/ydb/core/sys_view/auth/sort_helpers.h new file mode 100644 index 00000000000..55d46b188e8 --- /dev/null +++ b/ydb/core/sys_view/auth/sort_helpers.h @@ -0,0 +1,24 @@ +#pragma once + +#include <algorithm> +#include <util/generic/vector.h> +#include <util/system/yassert.h> + +namespace NKikimr::NSysView::NAuth { + +template<typename TElement, class TCompLess> +void SortBatch(TVector<TElement>& batch, TCompLess compLess, bool requireUnique = true) { + std::sort(batch.begin(), batch.end(), compLess); + + auto uniqueEnd = std::unique(batch.begin(), batch.end(), [&compLess](const TElement& left, const TElement& right) { + return !compLess(left, right) && !compLess(right, left); + }); + + if (requireUnique) { + Y_DEBUG_ABORT_UNLESS(uniqueEnd == batch.end()); + } else { + batch.erase(uniqueEnd, batch.end()); + } +} + +} diff --git a/ydb/core/sys_view/auth/users.cpp b/ydb/core/sys_view/auth/users.cpp index 374b410eef6..263ac0bd52e 100644 --- a/ydb/core/sys_view/auth/users.cpp +++ b/ydb/core/sys_view/auth/users.cpp @@ -1,5 +1,5 @@ -#include "auth_scan_base.h" #include "users.h" +#include "sort_helpers.h" #include <ydb/core/base/auth.h> #include <ydb/core/sys_view/common/events.h> @@ -94,53 +94,60 @@ protected: } void FillBatch(NKqp::TEvKqpCompute::TEvScanData& batch, const NKikimrScheme::TEvListUsersResult& result) { - TVector<TCell> cells(::Reserve(Columns.size())); - + TVector<const ::NKikimrScheme::TEvListUsersResult_TUser*> users(::Reserve(result.UsersSize())); for (const auto& user : result.GetUsers()) { if (!user.HasName() || !CanAccessUser(user.GetName())) { continue; } - + users.push_back(&user); + } + SortBatch(users, [](const auto* left, const auto* right) { + return left->GetName() < right->GetName(); + }); + + TVector<TCell> cells(::Reserve(Columns.size())); + + for (const auto* user : users) { for (auto& column : Columns) { switch (column.Tag) { case Schema::AuthUsers::Sid::ColumnId: - cells.push_back(user.HasName() - ? TCell(user.GetName().data(), user.GetName().size()) + cells.push_back(user->HasName() + ? TCell(user->GetName().data(), user->GetName().size()) : TCell()); break; case Schema::AuthUsers::IsEnabled::ColumnId: - cells.push_back(user.HasIsEnabled() - ? TCell::Make(user.GetIsEnabled()) + cells.push_back(user->HasIsEnabled() + ? TCell::Make(user->GetIsEnabled()) : TCell()); break; case Schema::AuthUsers::IsLockedOut::ColumnId: - cells.push_back(user.HasIsLockedOut() - ? TCell::Make(user.GetIsLockedOut()) + cells.push_back(user->HasIsLockedOut() + ? TCell::Make(user->GetIsLockedOut()) : TCell()); break; case Schema::AuthUsers::CreatedAt::ColumnId: - cells.push_back(user.HasCreatedAt() - ? TCell::Make(user.GetCreatedAt()) + cells.push_back(user->HasCreatedAt() + ? TCell::Make(user->GetCreatedAt()) : TCell()); break; case Schema::AuthUsers::LastSuccessfulAttemptAt::ColumnId: - cells.push_back(user.HasLastSuccessfulAttemptAt() - ? TCell::Make(user.GetLastSuccessfulAttemptAt()) + cells.push_back(user->HasLastSuccessfulAttemptAt() + ? TCell::Make(user->GetLastSuccessfulAttemptAt()) : TCell()); break; case Schema::AuthUsers::LastFailedAttemptAt::ColumnId: - cells.push_back(user.HasLastFailedAttemptAt() - ? TCell::Make(user.GetLastFailedAttemptAt()) + cells.push_back(user->HasLastFailedAttemptAt() + ? TCell::Make(user->GetLastFailedAttemptAt()) : TCell()); break; case Schema::AuthUsers::FailedAttemptCount::ColumnId: - cells.push_back(user.HasFailedAttemptCount() - ? TCell::Make(user.GetFailedAttemptCount()) + cells.push_back(user->HasFailedAttemptCount() + ? TCell::Make(user->GetFailedAttemptCount()) : TCell()); break; case Schema::AuthUsers::PasswordHash::ColumnId: - cells.push_back(user.HasPasswordHash() - ? TCell(user.GetPasswordHash().data(), user.GetPasswordHash().size()) + cells.push_back(user->HasPasswordHash() + ? TCell(user->GetPasswordHash().data(), user->GetPasswordHash().size()) : TCell()); break; default: diff --git a/ydb/core/sys_view/common/schema.h b/ydb/core/sys_view/common/schema.h index f81a882829a..8710a197a0f 100644 --- a/ydb/core/sys_view/common/schema.h +++ b/ydb/core/sys_view/common/schema.h @@ -667,7 +667,7 @@ struct Schema : NIceDb::Schema { struct Path: Column<1, NScheme::NTypeIds::Utf8> {}; struct Sid: Column<2, NScheme::NTypeIds::Utf8> {}; - using TKey = TableKey<Path, Sid>; + using TKey = TableKey<Path>; using TColumns = TableColumns< Path, Sid diff --git a/ydb/core/sys_view/ut_kqp.cpp b/ydb/core/sys_view/ut_kqp.cpp index 8d97010880c..434adf07511 100644 --- a/ydb/core/sys_view/ut_kqp.cpp +++ b/ydb/core/sys_view/ut_kqp.cpp @@ -2229,8 +2229,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["user4"];[%true];[%false];[0u];[0u];[0u]]; [["user3"];[%true];[%false];[0u];[0u];[0u]]; + [["user4"];[%true];[%false];[0u];[0u];[0u]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); @@ -2276,8 +2276,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["user2"]]; [["user1rootadmin"]]; + [["user2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2289,8 +2289,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["user4"]]; [["user3"]]; + [["user4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2335,6 +2335,47 @@ Y_UNIT_TEST_SUITE(SystemView) { // and test tenant user and tenant admin } + Y_UNIT_TEST(AuthUsers_ResultOrder) { + TTestEnv env; + SetupAuthEnvironment(env); + TTableClient client(env.GetDriver()); + + for (auto user : { + "user3", + "user1", + "user2", + "user", + "user33", + "user21", + "user22", + "userrr", + "u", + "asdf", + }) { + env.GetClient().CreateUser("/Root", user, "password"); + } + + auto it = client.StreamExecuteScanQuery(R"( + SELECT Sid + FROM `Root/.sys/auth_users` + )").GetValueSync(); + + auto expected = R"([ + [["asdf"]]; + [["u"]]; + [["user"]]; + [["user1"]]; + [["user2"]]; + [["user21"]]; + [["user22"]]; + [["user3"]]; + [["user33"]]; + [["userrr"]]; + ])"; + + NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); + } + Y_UNIT_TEST(AuthGroups) { TTestEnv env; SetupAuthEnvironment(env); @@ -2384,8 +2425,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group4"]]; [["group3"]]; + [["group4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); @@ -2433,8 +2474,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group2"]]; [["group1"]]; + [["group2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2446,8 +2487,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group4"]]; [["group3"]]; + [["group4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2486,7 +2527,48 @@ Y_UNIT_TEST_SUITE(SystemView) { // and test tenant user and tenant admin } - Y_UNIT_TEST(AuthMembers) { + Y_UNIT_TEST(AuthGroups_ResultOrder) { + TTestEnv env; + SetupAuthEnvironment(env); + TTableClient client(env.GetDriver()); + + for (auto group : { + "group3", + "group1", + "group2", + "group", + "group33", + "group21", + "group22", + "grouprr", + "g", + "asdf", + }) { + env.GetClient().CreateGroup("/Root", group); + } + + auto it = client.StreamExecuteScanQuery(R"( + SELECT * + FROM `Root/.sys/auth_groups` + )").GetValueSync(); + + auto expected = R"([ + [["asdf"]]; + [["g"]]; + [["group"]]; + [["group1"]]; + [["group2"]]; + [["group21"]]; + [["group22"]]; + [["group3"]]; + [["group33"]]; + [["grouprr"]]; + ])"; + + NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); + } + + Y_UNIT_TEST(AuthGroupMembers) { TTestEnv env; SetupAuthEnvironment(env); TTableClient client(env.GetDriver()); @@ -2545,18 +2627,18 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group4"];["group4"]]; + [["group3"];["user4"]]; [["group4"];["group3"]]; - [["group4"];["user4"]]; + [["group4"];["group4"]]; [["group4"];["user3"]]; - [["group3"];["user4"]]; + [["group4"];["user4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } } - Y_UNIT_TEST(AuthMembers_Access) { + Y_UNIT_TEST(AuthGroupMembers_Access) { TTestEnv env; SetupAuthAccessEnvironment(env); TTableClient client(env.GetDriver()); @@ -2602,8 +2684,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group2"];["user2"]]; [["group1"];["user1rootadmin"]]; + [["group2"];["user2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2615,8 +2697,8 @@ Y_UNIT_TEST_SUITE(SystemView) { )").GetValueSync(); auto expected = R"([ - [["group4"];["user4"]]; [["group3"];["user3"]]; + [["group4"];["user4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -2655,6 +2737,56 @@ Y_UNIT_TEST_SUITE(SystemView) { // and test tenant user and tenant admin } + Y_UNIT_TEST(AuthGroupMembers_ResultOrder) { + TTestEnv env; + SetupAuthEnvironment(env); + TTableClient client(env.GetDriver()); + + for (auto group : { + "group3", + "group1", + "group2", + "group", + }) { + env.GetClient().CreateGroup("/Root", group); + } + + for (auto user : { + "user1", + "user2", + "user" + }) { + env.GetClient().CreateUser("/Root", user, "password"); + } + + for (auto membership : TVector<std::pair<TString, TString>>{ + {"group3", "user1"}, + {"group3", "user2"}, + {"group2", "user"}, + {"group2", "user1"}, + {"group2", "user2"}, + {"group", "user2"}, + }) { + env.GetClient().AddGroupMembership("/Root", membership.first, membership.second); + } + + auto it = client.StreamExecuteScanQuery(R"( + SELECT * + FROM `Root/.sys/auth_group_members` + )").GetValueSync(); + + auto expected = R"([ + [["group"];["user2"]]; + [["group2"];["user"]]; + [["group2"];["user1"]]; + [["group2"];["user2"]]; + [["group3"];["user1"]]; + [["group3"];["user2"]]; + ])"; + + NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); + } + Y_UNIT_TEST(AuthOwners) { TTestEnv env; SetupAuthEnvironment(env); @@ -2859,6 +2991,53 @@ Y_UNIT_TEST_SUITE(SystemView) { // and test tenant user and tenant admin } + Y_UNIT_TEST(AuthOwners_ResultOrder) { + TTestEnv env; + SetupAuthEnvironment(env); + TTableClient client(env.GetDriver()); + + for (auto path : { + "Dir2/SubDir2", + "Dir1/SubDir1", + "Dir2/SubDir1", + "Dir1/SubDir2", + "Dir2/SubDir3", + "Dir1/SubDir3", + "Dir11/SubDir", + "Dir/SubDir", + }) { + env.GetClient().MkDir("/Root", path); + } + + auto it = client.StreamExecuteScanQuery(R"( + SELECT * + FROM `Root/.sys/auth_owners` + )").GetValueSync(); + + auto expected = R"([ + [["/Root"];["root@builtin"]]; + [["/Root/.metadata"];["metadata@system"]]; + [["/Root/.metadata/workload_manager"];["metadata@system"]]; + [["/Root/.metadata/workload_manager/pools"];["metadata@system"]]; + [["/Root/.metadata/workload_manager/pools/default"];["metadata@system"]]; + [["/Root/Dir"];["root@builtin"]]; + [["/Root/Dir/SubDir"];["root@builtin"]]; + [["/Root/Dir1"];["root@builtin"]]; + [["/Root/Dir1/SubDir1"];["root@builtin"]]; + [["/Root/Dir1/SubDir2"];["root@builtin"]]; + [["/Root/Dir1/SubDir3"];["root@builtin"]]; + [["/Root/Dir11"];["root@builtin"]]; + [["/Root/Dir11/SubDir"];["root@builtin"]]; + [["/Root/Dir2"];["root@builtin"]]; + [["/Root/Dir2/SubDir1"];["root@builtin"]]; + [["/Root/Dir2/SubDir2"];["root@builtin"]]; + [["/Root/Dir2/SubDir3"];["root@builtin"]]; + [["/Root/Table0"];["root@builtin"]] + ])"; + + NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); + } + Y_UNIT_TEST(AuthPermissions) { TTestEnv env; SetupAuthEnvironment(env); @@ -2925,13 +3104,13 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root"];["ydb.generic.use"];["user1"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["all-users@well-known"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; [["/Root/Dir1"];["ydb.generic.use"];["user1"]]; - [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user1"]]; [["/Root/Dir1/SubDir1"];["ydb.granular.erase_row"];["user1"]]; + [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user1"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); @@ -3009,14 +3188,14 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root"];["ydb.generic.use"];["user1rootadmin"]]; [["/Root"];["ydb.generic.use"];["user2"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["all-users@well-known"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; [["/Root/Dir1"];["ydb.granular.select_row"];["user1rootadmin"]]; - [["/Root/Dir2"];["ydb.granular.erase_row"];["user2"]] + [["/Root/Dir2"];["ydb.granular.erase_row"];["user2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -3040,14 +3219,14 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root"];["ydb.generic.use"];["user1rootadmin"]]; [["/Root"];["ydb.generic.use"];["user2"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["all-users@well-known"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; [["/Root/Dir1"];["ydb.granular.select_row"];["user1rootadmin"]]; - [["/Root/Dir2"];["ydb.granular.erase_row"];["user2"]] + [["/Root/Dir2"];["ydb.granular.erase_row"];["user2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -3060,7 +3239,7 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root/Tenant1/Dir3"];["ydb.granular.select_row"];["user3"]]; - [["/Root/Tenant1/Dir3"];["ydb.granular.erase_row"];["user4"]] + [["/Root/Tenant1/Dir3"];["ydb.granular.erase_row"];["user4"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); } @@ -3088,12 +3267,12 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root"];["ydb.generic.use"];["user1rootadmin"]]; [["/Root"];["ydb.generic.use"];["user2"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["all-users@well-known"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["root@builtin"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.full"];["user1rootadmin"]]; [["/Root/Dir1"];["ydb.granular.select_row"];["user1rootadmin"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); @@ -3103,6 +3282,76 @@ Y_UNIT_TEST_SUITE(SystemView) { // and test tenant user and tenant admin } + Y_UNIT_TEST(AuthPermissions_ResultOrder) { + TTestEnv env; + SetupAuthEnvironment(env); + TTableClient client(env.GetDriver()); + + for (auto user : { + "user1", + "user2", + "user" + }) { + env.GetClient().CreateUser("/Root", user, "password"); + } + + for (auto dir : { + "Dir", + "Dir1", + "Dir2", + "Dir/SubDir1", + "Dir/SubDir2" + }) { + env.GetClient().MkDir("/Root", dir); + } + + for (auto acl : TVector<std::tuple<TString, TString, TString, NACLib::EAccessRights>>{ + {"/", "Root", "user1", NACLib::SelectRow}, + {"/", "Root", "user1", NACLib::EraseRow}, + {"/", "Root", "user1", NACLib::AlterSchema}, + {"/", "Root", "user2", NACLib::GenericUse}, + {"/Root", "Dir1", "user2", NACLib::GenericUse}, + {"/Root", "Dir1", "user1", NACLib::GenericUse}, + {"/Root", "Dir2", "user2", NACLib::GenericUse}, + {"/Root", "Dir2", "user", NACLib::GenericUse}, + {"/Root", "Dir2", "user1", NACLib::GenericUse}, + {"/Root", "Dir", "user1", NACLib::GenericUse}, + {"/Root", "Dir1", "user1", NACLib::AlterSchema}, + {"/Root/Dir1", "SubDir1", "user1", NACLib::AlterSchema}, + {"/Root/Dir1", "SubDir2", "user2", NACLib::AlterSchema}, + {"/Root/Dir1", "SubDir2", "user1", NACLib::AlterSchema} + }) { + NACLib::TDiffACL diffAcl; + diffAcl.AddAccess(NACLib::EAccessType::Allow, std::get<3>(acl), std::get<2>(acl)); + env.GetClient().ModifyACL(std::get<0>(acl), std::get<1>(acl), diffAcl.SerializeAsString()); + } + + auto it = client.StreamExecuteScanQuery(R"( + SELECT Path, Sid, Permission + FROM `Root/.sys/auth_permissions` + )").GetValueSync(); + + auto expected = R"([ + [["/Root"];["user1"];["ydb.granular.alter_schema"]]; + [["/Root"];["user1"];["ydb.granular.erase_row"]]; + [["/Root"];["user1"];["ydb.granular.select_row"]]; + [["/Root"];["user2"];["ydb.generic.use"]]; + [["/Root/.metadata/workload_manager/pools/default"];["all-users@well-known"];["ydb.granular.describe_schema"]]; + [["/Root/.metadata/workload_manager/pools/default"];["all-users@well-known"];["ydb.granular.select_row"]]; + [["/Root/.metadata/workload_manager/pools/default"];["root@builtin"];["ydb.granular.describe_schema"]]; + [["/Root/.metadata/workload_manager/pools/default"];["root@builtin"];["ydb.granular.select_row"]]; + [["/Root/Dir"];["user1"];["ydb.generic.use"]]; + [["/Root/Dir1"];["user1"];["ydb.generic.use"]]; + [["/Root/Dir1"];["user1"];["ydb.granular.alter_schema"]]; + [["/Root/Dir1"];["user2"];["ydb.generic.use"]]; + [["/Root/Dir2"];["user"];["ydb.generic.use"]]; + [["/Root/Dir2"];["user1"];["ydb.generic.use"]]; + [["/Root/Dir2"];["user2"];["ydb.generic.use"]]; + ])"; + + NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); + } + Y_UNIT_TEST(AuthEffectivePermissions) { TTestEnv env; SetupAuthEnvironment(env); @@ -3138,11 +3387,11 @@ Y_UNIT_TEST_SUITE(SystemView) { [["/Root/.metadata"];["ydb.generic.use"];["user1"]]; [["/Root/.metadata/workload_manager"];["ydb.generic.use"];["user1"]]; [["/Root/.metadata/workload_manager/pools"];["ydb.generic.use"];["user1"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.use"];["user1"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["all-users@well-known"]]; - [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["all-users@well-known"]]; [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.describe_schema"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.granular.select_row"];["root@builtin"]]; + [["/Root/.metadata/workload_manager/pools/default"];["ydb.generic.use"];["user1"]]; [["/Root/Dir1"];["ydb.generic.use"];["user1"]]; [["/Root/Table0"];["ydb.generic.use"];["user1"]] ])"; @@ -3234,8 +3483,8 @@ Y_UNIT_TEST_SUITE(SystemView) { auto expected = R"([ [["/Root/Dir1"];["ydb.granular.select_row"];["user2"]]; - [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user2"]]; [["/Root/Dir1/SubDir1"];["ydb.granular.erase_row"];["user2"]]; + [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user2"]]; ])"; NKqp::CompareYson(expected, NKqp::StreamResultToYson(it)); @@ -3248,12 +3497,10 @@ Y_UNIT_TEST_SUITE(SystemView) { WHERE Sid = "user2" )").GetValueSync(); - // TODO: make result unique auto expected = R"([ [["/Root/Dir1"];["ydb.granular.select_row"];["user2"]]; - [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user2"]]; - [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user2"]]; [["/Root/Dir1/SubDir1"];["ydb.granular.erase_row"];["user2"]]; + [["/Root/Dir1/SubDir1"];["ydb.granular.select_row"];["user2"]]; [["/Root/Dir1/SubDir2"];["ydb.granular.select_row"];["user2"]]; ])"; |
