Skip to content

SystemView Auth Sort results #13904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions ydb/core/sys_view/auth/auth_scan_base.h
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -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:
Expand Down Expand Up @@ -96,9 +113,9 @@ class TAuthScanBase : public TScanActorBase<TDerived> {
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;
Expand Down
43 changes: 26 additions & 17 deletions ydb/core/sys_view/auth/group_members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,36 @@ class TGroupMembersScan : public TAuthScanBase<TGroupMembersScan> {
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;
Expand Down
12 changes: 10 additions & 2 deletions ydb/core/sys_view/auth/groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,22 @@ class TGroupsScan : public TAuthScanBase<TGroupsScan> {
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();
Expand Down
62 changes: 36 additions & 26 deletions ydb/core/sys_view/auth/permissions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ class TPermissionsScan : public TAuthScanBase<TPermissionsScan> {
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;
Expand All @@ -49,32 +46,45 @@ class TPermissionsScan : public TAuthScanBase<TPermissionsScan> {
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;
Expand Down
24 changes: 24 additions & 0 deletions ydb/core/sys_view/auth/sort_helpers.h
Original file line number Diff line number Diff line change
@@ -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());
}
}

}
47 changes: 27 additions & 20 deletions ydb/core/sys_view/auth/users.cpp
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -94,53 +94,60 @@ class TUsersScan : public TScanActorBase<TUsersScan> {
}

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:
Expand Down
2 changes: 1 addition & 1 deletion ydb/core/sys_view/common/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading