Skip to content

Commit

Permalink
[TicketParser] Use folder_id attribute for container_id (ydb-platform…
Browse files Browse the repository at this point in the history
  • Loading branch information
UgnineSirdis authored and MrLolthe1st committed May 28, 2024
1 parent 7331016 commit c8a9a77
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 38 deletions.
51 changes: 28 additions & 23 deletions ydb/core/security/ticket_parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,25 +386,8 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
resourcePath->set_type(type);
}

template <>
static void AddResourcePath<nebius::iam::v1::AuthorizeCheck*>(nebius::iam::v1::AuthorizeCheck* pathsContainer, const TString& id, const TString& type) {
auto resourcePath = pathsContainer->mutable_resource_path()->add_path();
resourcePath->set_id(id);
Y_UNUSED(type);
}

template <typename TPathsContainerPtr>
static void AddContainerId(TPathsContainerPtr pathsContainer, const TString& id) {
Y_UNUSED(pathsContainer, id);
}

template <>
static void AddContainerId<nebius::iam::v1::AuthorizeCheck*>(nebius::iam::v1::AuthorizeCheck* pathsContainer, const TString& id) {
pathsContainer->set_container_id(id);
}

template <typename TTokenRecord, typename TPathsContainerPtr>
void addResourcePaths(const TTokenRecord& record, const TString& permission, TPathsContainerPtr pathsContainer) const {
void AddResourcePaths(const TTokenRecord& record, const TString& permission, TPathsContainerPtr pathsContainer) const {
if (const auto databaseId = record.GetAttributeValue(permission, "database_id"); databaseId) {
AddResourcePath(pathsContainer, databaseId, "ydb.database");
} else if (const auto serviceAccountId = record.GetAttributeValue(permission, "service_account_id"); serviceAccountId) {
Expand All @@ -422,9 +405,28 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
if (const TString gizmoId = record.GetAttributeValue(permission, "gizmo_id"); gizmoId) {
AddResourcePath(pathsContainer, gizmoId, "iam.gizmo");
}
}

if (const TString containerId = record.GetAttributeValue(permission, "container_id"); containerId) {
AddContainerId(pathsContainer, containerId);
static void AddNebiusResourcePath(nebius::iam::v1::AuthorizeCheck* pathsContainer, const TString& id) {
pathsContainer->mutable_resource_path()->add_path()->set_id(id);
}

static void AddNebiusContainerId(nebius::iam::v1::AuthorizeCheck* pathsContainer, const TString& id) {
pathsContainer->set_container_id(id);
}

template <typename TTokenRecord>
void AddNebiusResourcePaths(const TTokenRecord& record, const TString& permission, nebius::iam::v1::AuthorizeCheck* pathsContainer) const {
// Use attribute "database_id" as our resource id
// IAM can link roles for resource
if (const auto databaseId = record.GetAttributeValue(permission, "database_id"); databaseId) {
AddNebiusResourcePath(pathsContainer, databaseId);
}

// Use attribute "folder_id" as container id that contains our database
// IAM can link roles for containers hierarchy
if (const auto folderId = record.GetAttributeValue(permission, "folder_id"); folderId) {
AddNebiusContainerId(pathsContainer, folderId);
}
}

Expand All @@ -435,7 +437,7 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {

auto request = CreateAccessServiceRequest<TEvAccessServiceAuthorizeRequest>(key, record);
request->Request.set_permission(permissionName);
addResourcePaths(record, permissionName, &request->Request);
AddResourcePaths(record, permissionName, &request->Request);
record.ResponsesLeft++;
Send(AccessServiceValidatorV1, request.Release());
}
Expand All @@ -447,7 +449,7 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
TStringBuilder requestForPermissions;
for (const auto& [permissionName, permissionRecord] : record.Permissions) {
auto action = request->Request.mutable_actions()->add_items();
addResourcePaths(record, permissionName, action);
AddResourcePaths(record, permissionName, action);
action->set_permission(permissionName);
requestForPermissions << " " << permissionName;
}
Expand All @@ -466,7 +468,7 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
auto& check = (*request->Request.mutable_checks())[i];
check.set_iam_token(record.Ticket);
check.mutable_permission()->set_name(permissionName);
addResourcePaths(record, permissionName, &check);
AddNebiusResourcePaths(record, permissionName, &check);
requestForPermissions << " " << permissionName;
++i;
}
Expand Down Expand Up @@ -1082,6 +1084,9 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
if (permissionRecord.IsRequired()) {
hasRequiredPermissionFailed = true;
errorMessage << permissionIt->first << " for";
if (check.container_id()) {
errorMessage << ' ' << check.container_id();
}
for (const auto& resourcePath : check.resource_path().path()) {
errorMessage << ' ' << resourcePath.id();
}
Expand Down
42 changes: 27 additions & 15 deletions ydb/core/security/ticket_parser_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1668,8 +1668,7 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {

TVector<std::pair<TString, TString>> attrs = {{"folder_id", "aaaa1234"}, {"database_id", "bbbb4554"}};
if constexpr (IsNebiusAccessService<TAccessServiceMock>()) {
accessServiceMock.ContainerId = "my_container";
attrs.emplace_back("container_id", "my_container");
accessServiceMock.ContainerId = "aaaa1234";
}

// Authorization successful.
Expand Down Expand Up @@ -1771,7 +1770,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
UNIT_ASSERT(!result->Error.Retryable);
UNIT_ASSERT_VALUES_EQUAL(result->Error.Message, "Access Denied");

// Authorization successful with right folder_id.
if constexpr (IsNebiusAccessService<TAccessServiceMock>()) {
accessServiceMock.ContainerId = "aaaa1234";
}
accessServiceMock.AllowedResourceIds.clear();
accessServiceMock.AllowedResourceIds.emplace("aaaa1234");
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(
userToken,
Expand All @@ -1781,8 +1783,13 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
UNIT_ASSERT_C(result->Error.empty(), result->Error);
UNIT_ASSERT_C(result->Token->IsExist("something.read-XXXXXXXX@as"), result->Token->ShortDebugString());

if constexpr (IsNebiusAccessService<TAccessServiceMock>()) {
accessServiceMock.ContainerId = "";
} else {
accessServiceMock.AllowedResourceIds.clear();
}

// Authorization successful with right database_id.
accessServiceMock.AllowedResourceIds.clear();
accessServiceMock.AllowedResourceIds.emplace("bbbb4554");
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(
userToken,
Expand All @@ -1792,17 +1799,19 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
UNIT_ASSERT_C(result->Error.empty(), result->Error);
UNIT_ASSERT_C(result->Token->IsExist("something.read-bbbb4554@as"), result->Token->ShortDebugString());

// Authorization successful for gizmo resource
accessServiceMock.AllowedResourceIds.clear();
accessServiceMock.AllowedResourceIds.emplace("gizmo");
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(
userToken,
{{"gizmo_id", "gizmo"}, },
{"monitoring.view"})), 0);
result = runtime->GrabEdgeEvent<TEvTicketParser::TEvAuthorizeTicketResult>(handle);
UNIT_ASSERT_C(result->Error.empty(), result->Error);
UNIT_ASSERT_C(result->Token->IsExist("monitoring.view@as"), result->Token->ShortDebugString());
UNIT_ASSERT_C(result->Token->IsExist("monitoring.view-gizmo@as"), result->Token->ShortDebugString());
if constexpr (!IsNebiusAccessService<TAccessServiceMock>()) {
// Authorization successful for gizmo resource
accessServiceMock.AllowedResourceIds.clear();
accessServiceMock.AllowedResourceIds.emplace("gizmo");
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(
userToken,
{{"gizmo_id", "gizmo"}, },
{"monitoring.view"})), 0);
result = runtime->GrabEdgeEvent<TEvTicketParser::TEvAuthorizeTicketResult>(handle);
UNIT_ASSERT_C(result->Error.empty(), result->Error);
UNIT_ASSERT_C(result->Token->IsExist("monitoring.view@as"), result->Token->ShortDebugString());
UNIT_ASSERT_C(result->Token->IsExist("monitoring.view-gizmo@as"), result->Token->ShortDebugString());
}
}

Y_UNIT_TEST(Authorization) {
Expand Down Expand Up @@ -1848,6 +1857,9 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {

// Access Server Mock
TAccessServiceMock accessServiceMock;
if constexpr (IsNebiusAccessService<TAccessServiceMock>()) {
accessServiceMock.ContainerId = "aaaa1234";
}
grpc::ServerBuilder builder;
builder.AddListeningPort(accessServiceEndpoint, grpc::InsecureServerCredentials()).RegisterService(&accessServiceMock);
std::unique_ptr<grpc::Server> accessServer(builder.BuildAndStart());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ class TTicketParserNebiusAccessServiceMock : public nebius::iam::v1::AccessServi
bool allowedResource = true;
if (!AllowedResourceIds.empty()) {
allowedResource = false;
if (IsIn(AllowedResourceIds, check.container_id())) {
allowedResource = true;
}
for (const auto& resourcePath : check.resource_path().path()) {
if (IsIn(AllowedResourceIds, resourcePath.id())) {
allowedResource = true;
Expand Down

0 comments on commit c8a9a77

Please sign in to comment.