Skip to content

Commit

Permalink
small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
molotkov-and committed Jan 19, 2024
1 parent 8252833 commit a16f023
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 98 deletions.
189 changes: 94 additions & 95 deletions ydb/core/security/ticket_parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,7 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {

template <typename TTokenRecord>
void AccessServiceAuthorize(const TString& key, TTokenRecord& record) const {
for (const auto& [permissionName, permRecord] : record.Permissions) {
// const TString& permission(perm);
for (const auto& [permissionName, permissionRecord] : record.Permissions) {
BLOG_TRACE("Ticket " << record.GetMaskedTicket() << " asking for AccessServiceAuthorization(" << permissionName << ")");

auto request = CreateAccessServiceRequest<TEvAccessServiceAuthorizeRequest>(key, record);
Expand Down Expand Up @@ -791,6 +790,19 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
}
}

template <typename TTokenRecord>
void SetAccessServiceBulkAuthorizeError(const TString& key, TTokenRecord& record, const TString& errorMessage, bool isRetryableError) {
for (auto& [permissionName, permissionRecord] : record.Permissions) {
permissionRecord.Subject.clear();
permissionRecord.Error = {.Message = errorMessage, .Retryable = isRetryableError};
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " permission " << permissionName
<< " now has a " << (isRetryableError ? "retryable" : "permanent") << " error \"" << errorMessage << "\""
<< " retryable: " << isRetryableError);
}
SetError(key, record, {.Message = errorMessage, .Retryable = isRetryableError});
}

void Handle(NCloud::TEvAccessService::TEvBulkAuthorizeResponse::TPtr& ev) {
auto getResourcePathIdForRequiredPermissions = [] (const ::yandex::cloud::priv::accessservice::v2::Resource& resource_path) -> TString {
if (resource_path.type() == "resource-manager.folder") {
Expand Down Expand Up @@ -819,107 +831,94 @@ class TTicketParserImpl : public TActorBootstrapped<TDerived> {
--record.ResponsesLeft;
auto& examinedPermissions = record.Permissions;
if (response->Status.Ok()) {
const auto& subject = response->Response.subject();
const TString subjectName = GetSubjectName(subject);
const auto& subjectType = ConvertSubjectType(subject.type_case());
for (auto& [permissionName, permissionRecord] : examinedPermissions) {
permissionRecord.Subject = subjectName;
permissionRecord.SubjectType = subjectType;
permissionRecord.Error.clear();
}
size_t permissionDeniedCount = 0;
bool hasRequiredPermissionFailed = false;
std::vector<typename THashMap<TString, TPermissionRecord>::iterator> requiredPermissions;
TString permissionDeniedError;
const auto& results = response->Response.results();
for (const auto& result : results.items()) {
auto permissionDeniedIt = examinedPermissions.find(result.permission());
if (permissionDeniedIt != examinedPermissions.end()) {
permissionDeniedCount++;
auto& permissionDeniedRecord = permissionDeniedIt->second;
permissionDeniedRecord.Subject.clear();
BLOG_TRACE("Ticket " << record.GetMaskedTicket() << " permission " << result.permission() << " access denied for subject \"" << subjectName << "\"");
TStringBuilder errorMessage;
if (permissionDeniedRecord.IsRequired()) {
hasRequiredPermissionFailed = true;
errorMessage << permissionDeniedIt->first << " for";
for (const auto& resourcePath : result.resource_path()) {
errorMessage << getResourcePathIdForRequiredPermissions(resourcePath);
}
errorMessage << " - ";
requiredPermissions.push_back(permissionDeniedIt);
}
permissionDeniedError = result.permission_denied_error().message();;
errorMessage << permissionDeniedError;
permissionDeniedRecord.Error = {.Message = errorMessage, .Retryable = false};
} else {
BLOG_W("Received response for unknown permission " << result.permission() << " for ticket " << record.GetMaskedTicket());
if (response->Response.has_unauthenticated_error()) {
SetAccessServiceBulkAuthorizeError(key, record, response->Response.unauthenticated_error().message(), false);
} else {
const auto& subject = response->Response.subject();
const TString subjectName = GetSubjectName(subject);
const auto& subjectType = ConvertSubjectType(subject.type_case());
for (auto& [permissionName, permissionRecord] : examinedPermissions) {
permissionRecord.Subject = subjectName;
permissionRecord.SubjectType = subjectType;
permissionRecord.Error.clear();
}
}
if (permissionDeniedCount < examinedPermissions.size() && !hasRequiredPermissionFailed) {
record.TokenType = request->Request.has_api_key() ? TDerived::ETokenType::ApiKey : TDerived::ETokenType::AccessService;
switch (subjectType) {
case TPermissionRecord::TTypeCase::USER_ACCOUNT_TYPE:
if (UserAccountService) {
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " asking for UserAccount(" << subjectName << ")");
THolder<TEvAccessServiceGetUserAccountRequest> request = MakeHolder<TEvAccessServiceGetUserAccountRequest>(key);
request->Token = record.Ticket;
request->Request.set_user_account_id(subject.user_account().id());
record.ResponsesLeft++;
Send(UserAccountService, request.Release());
return;
}
break;
case TPermissionRecord::TTypeCase::SERVICE_ACCOUNT_TYPE:
if (ServiceAccountService) {
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " asking for ServiceAccount(" << subjectName << ")");
THolder<TEvAccessServiceGetServiceAccountRequest> request = MakeHolder<TEvAccessServiceGetServiceAccountRequest>(key);
request->Token = record.Ticket;
request->Request.set_service_account_id(subject.service_account().id());
record.ResponsesLeft++;
Send(ServiceAccountService, request.Release());
return;
size_t permissionDeniedCount = 0;
bool hasRequiredPermissionFailed = false;
std::vector<typename THashMap<TString, TPermissionRecord>::iterator> requiredPermissions;
TString permissionDeniedError;
const auto& results = response->Response.results();
for (const auto& result : results.items()) {
auto permissionDeniedIt = examinedPermissions.find(result.permission());
if (permissionDeniedIt != examinedPermissions.end()) {
permissionDeniedCount++;
auto& permissionDeniedRecord = permissionDeniedIt->second;
permissionDeniedRecord.Subject.clear();
BLOG_TRACE("Ticket " << record.GetMaskedTicket() << " permission " << result.permission() << " access denied for subject \"" << subjectName << "\"");
TStringBuilder errorMessage;
if (permissionDeniedRecord.IsRequired()) {
hasRequiredPermissionFailed = true;
errorMessage << permissionDeniedIt->first << " for";
for (const auto& resourcePath : result.resource_path()) {
errorMessage << getResourcePathIdForRequiredPermissions(resourcePath);
}
errorMessage << " - ";
requiredPermissions.push_back(permissionDeniedIt);
}
permissionDeniedError = result.permission_denied_error().message();;
errorMessage << permissionDeniedError;
permissionDeniedRecord.Error = {.Message = errorMessage, .Retryable = false};
} else {
BLOG_W("Received response for unknown permission " << result.permission() << " for ticket " << record.GetMaskedTicket());
}
break;
default:
break;
}
SetToken(request->Key, record, new NACLib::TUserToken(record.Ticket, subjectName, {}));
} else {
if (hasRequiredPermissionFailed) {
TStringBuilder errorMessage;
auto it = requiredPermissions.cbegin();
errorMessage << (*it)->second.Error.Message;
++it;
for (; it != requiredPermissions.cend(); ++it) {
errorMessage << ", " << (*it)->second.Error.Message;
if (permissionDeniedCount < examinedPermissions.size() && !hasRequiredPermissionFailed) {
record.TokenType = request->Request.has_api_key() ? TDerived::ETokenType::ApiKey : TDerived::ETokenType::AccessService;
switch (subjectType) {
case TPermissionRecord::TTypeCase::USER_ACCOUNT_TYPE:
if (UserAccountService) {
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " asking for UserAccount(" << subjectName << ")");
THolder<TEvAccessServiceGetUserAccountRequest> request = MakeHolder<TEvAccessServiceGetUserAccountRequest>(key);
request->Token = record.Ticket;
request->Request.set_user_account_id(subject.user_account().id());
record.ResponsesLeft++;
Send(UserAccountService, request.Release());
return;
}
break;
case TPermissionRecord::TTypeCase::SERVICE_ACCOUNT_TYPE:
if (ServiceAccountService) {
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " asking for ServiceAccount(" << subjectName << ")");
THolder<TEvAccessServiceGetServiceAccountRequest> request = MakeHolder<TEvAccessServiceGetServiceAccountRequest>(key);
request->Token = record.Ticket;
request->Request.set_service_account_id(subject.service_account().id());
record.ResponsesLeft++;
Send(ServiceAccountService, request.Release());
return;
}
break;
default:
break;
}
SetError(key, record, {.Message = errorMessage, .Retryable = false});
SetToken(request->Key, record, new NACLib::TUserToken(record.Ticket, subjectName, {}));
} else {
SetError(key, record, {.Message = permissionDeniedError, .Retryable = false});
if (hasRequiredPermissionFailed) {
TStringBuilder errorMessage;
auto it = requiredPermissions.cbegin();
errorMessage << (*it)->second.Error.Message;
++it;
for (; it != requiredPermissions.cend(); ++it) {
errorMessage << ", " << (*it)->second.Error.Message;
}
SetError(key, record, {.Message = errorMessage, .Retryable = false});
} else {
SetError(key, record, {.Message = permissionDeniedError, .Retryable = false});
}
}
}
} else {
TString grpsErrorMessage;
bool isRetryableGrpsError = false;
if (response->Response.has_unauthenticated_error()) {
grpsErrorMessage = response->Response.unauthenticated_error().message();
isRetryableGrpsError = false;
} else {
grpsErrorMessage = response->Status.Msg;
isRetryableGrpsError = IsRetryableGrpcError(response->Status);
}
for (auto& [permissionName, permissionRecord] : examinedPermissions) {
permissionRecord.Subject.clear();
permissionRecord.Error = {.Message = grpsErrorMessage, .Retryable = isRetryableGrpsError};
BLOG_TRACE("Ticket " << record.GetMaskedTicket()
<< " permission " << permissionName
<< " now has a " << (isRetryableGrpsError ? "retryable" : "permanent") << " error \"" << grpsErrorMessage << "\""
<< " retryable: " << isRetryableGrpsError);
}
SetError(key, record, {.Message = grpsErrorMessage, .Retryable = isRetryableGrpsError});
SetAccessServiceBulkAuthorizeError(key, record, response->Status.Msg, IsRetryableGrpcError(response->Status));
}
Respond(record);
}
Expand Down
2 changes: 1 addition & 1 deletion ydb/library/testlib/service_mocks/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SRCS(
)

PEERDIR(
# ydb/public/api/client/yc_private/servicecontrol
ydb/public/api/client/yc_private/servicecontrol
ydb/public/api/client/yc_private/accessservice
ydb/public/api/grpc/draft
ydb/public/api/client/yc_private/resourcemanager
Expand Down
2 changes: 1 addition & 1 deletion ydb/library/ycloud/api/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SRCS(

PEERDIR(
ydb/public/api/client/yc_private/iam
# ydb/public/api/client/yc_private/servicecontrol
ydb/public/api/client/yc_private/servicecontrol
ydb/public/api/client/yc_private/accessservice
ydb/public/api/client/yc_private/resourcemanager
ydb/library/actors/core
Expand Down
1 change: 0 additions & 1 deletion ydb/library/ycloud/impl/mock_access_service.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <ydb/library/actors/core/actorsystem.h>
#include <ydb/library/actors/core/actor.h>
#include <library/cpp/json/json_value.h>
#include <ydb/public/api/client/yc_private/accessservice/access_service.grpc.pb.h>
#include "access_service.h"
#include "grpc_service_client.h"
#include "grpc_service_cache.h"
Expand Down

0 comments on commit a16f023

Please sign in to comment.