aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhcpp <hcpp@yandex-team.ru>2022-04-25 11:20:43 +0300
committerhcpp <hcpp@yandex-team.ru>2022-04-25 11:20:43 +0300
commit0ecf27e611841e6dfdadc80e67f80be091e0ccc7 (patch)
treef140fb86514195335914d9678b2c4b76bad10ba5
parent26a47007a80a1805a801dafff0c03dc13b88df3f (diff)
downloadydb-0ecf27e611841e6dfdadc80e67f80be091e0ccc7.tar.gz
PR from branch users/hcpp/required_permissions YQ-973
base template auth error has been added ref:412889637a6da80069cd596f1308061d73087cf4
-rw-r--r--ydb/core/base/ticket_parser.h51
-rw-r--r--ydb/core/grpc_services/base/base.h15
-rw-r--r--ydb/core/grpc_services/grpc_request_check_actor.h1
-rw-r--r--ydb/core/grpc_services/service_yq.h20
-rw-r--r--ydb/core/security/ticket_parser.cpp2
-rw-r--r--ydb/services/yq/grpc_service.cpp300
6 files changed, 266 insertions, 123 deletions
diff --git a/ydb/core/base/ticket_parser.h b/ydb/core/base/ticket_parser.h
index 5ebde54b6cb..d1b8454e6b9 100644
--- a/ydb/core/base/ticket_parser.h
+++ b/ydb/core/base/ticket_parser.h
@@ -25,9 +25,45 @@ namespace NKikimr {
static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_TICKET_PARSER), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_TICKET_PARSER)");
struct TEvAuthorizeTicket : TEventLocal<TEvAuthorizeTicket, EvAuthorizeTicket> {
+ struct TPermission {
+ TString Permission;
+ bool Required = false;
+ };
+
+ static TPermission Required(const TString& permission) {
+ return {
+ .Permission = permission,
+ .Required = true
+ };
+ }
+
+ static TPermission Optional(const TString& permission) {
+ return {
+ .Permission = permission,
+ .Required = false
+ };
+ }
+
+ static TVector<TPermission> ToPermissions(const TVector<TString>& permissions) {
+ TVector<TPermission> result;
+ std::transform(permissions.begin(), permissions.end(), std::back_inserter(result),
+ [](const TString& s) { return Optional(s); });
+ return result;
+ }
+
struct TEntry {
- TStackVec<TString> Permissions;
+ TStackVec<TPermission> Permissions;
TStackVec<std::pair<TString, TString>> Attributes;
+
+ TEntry(const TVector<TString>& permissions, const TVector<std::pair<TString, TString>>& attributes)
+ : Permissions(ToPermissions(permissions))
+ , Attributes(attributes)
+ {}
+
+ TEntry(const TVector<TPermission>& permissions, const TVector<std::pair<TString, TString>>& attributes)
+ : Permissions(permissions)
+ , Attributes(attributes)
+ {}
};
const TString Database;
@@ -76,12 +112,23 @@ namespace NKikimr {
TEvAuthorizeTicket(const TString& ticket, const TVector<std::pair<TString, TString>>& attributes, const TVector<TString>& permissions)
: Ticket(ticket)
- , Entries({{permissions, attributes}})
+ , Entries({{ToPermissions(permissions), attributes}})
{}
TEvAuthorizeTicket(const TString& ticket, const TString& peerName, const TVector<std::pair<TString, TString>>& attributes, const TVector<TString>& permissions)
: Ticket(ticket)
, PeerName(peerName)
+ , Entries({{ToPermissions(permissions), attributes}})
+ {}
+
+ TEvAuthorizeTicket(const TString& ticket, const TVector<std::pair<TString, TString>>& attributes, const TVector<TPermission>& permissions)
+ : Ticket(ticket)
+ , Entries({{permissions, attributes}})
+ {}
+
+ TEvAuthorizeTicket(const TString& ticket, const TString& peerName, const TVector<std::pair<TString, TString>>& attributes, const TVector<TPermission>& permissions)
+ : Ticket(ticket)
+ , PeerName(peerName)
, Entries({{permissions, attributes}})
{}
diff --git a/ydb/core/grpc_services/base/base.h b/ydb/core/grpc_services/base/base.h
index 5b8c53c5ec9..4aa27a5ba4e 100644
--- a/ydb/core/grpc_services/base/base.h
+++ b/ydb/core/grpc_services/base/base.h
@@ -611,8 +611,12 @@ public:
}
void ReplyUnauthenticated(const TString& in) override {
- const TString message = in.empty() ? TString("unauthenticated") : TString("unauthenticated, ") + in;
- Ctx_->Finish(grpc::Status(grpc::StatusCode::UNAUTHENTICATED, message));
+ TStringBuilder builder;
+ builder << (in.empty() ? TString("unauthenticated") : TString("unauthenticated, ")) << in;
+ for (const auto& issue: IssueManager_.GetIssues()) {
+ builder << " " << issue.Message;
+ }
+ Ctx_->Finish(grpc::Status(grpc::StatusCode::UNAUTHENTICATED, builder));
}
void ReplyUnavaliable() override {
@@ -867,7 +871,12 @@ public:
}
void ReplyUnauthenticated(const TString& in) override {
- Ctx_->ReplyUnauthenticated(in);
+ TStringBuilder builder;
+ builder << in;
+ for (const auto& issue: IssueManager.GetIssues()) {
+ builder << " " << issue.Message;
+ }
+ Ctx_->ReplyUnauthenticated(builder);
}
void SetInternalToken(const TString& token) override {
diff --git a/ydb/core/grpc_services/grpc_request_check_actor.h b/ydb/core/grpc_services/grpc_request_check_actor.h
index 52342d0108a..869e3ea23e4 100644
--- a/ydb/core/grpc_services/grpc_request_check_actor.h
+++ b/ydb/core/grpc_services/grpc_request_check_actor.h
@@ -34,6 +34,7 @@ public:
} else {
GrpcRequestBaseCtx_->UpdateAuthState(NGrpc::TAuthState::AS_FAIL);
}
+ GrpcRequestBaseCtx_->RaiseIssue(NYql::TIssue{error.Message});
ReplyBackAndDie();
}
diff --git a/ydb/core/grpc_services/service_yq.h b/ydb/core/grpc_services/service_yq.h
index 85b5a3ced80..9453dd4b7dd 100644
--- a/ydb/core/grpc_services/service_yq.h
+++ b/ydb/core/grpc_services/service_yq.h
@@ -14,42 +14,42 @@ class IFacilityProvider;
template <typename TReq, typename TResp>
class TGrpcYqRequestOperationCall : public TGrpcRequestOperationCall<TReq, TResp> {
-
public:
using TBase = TGrpcRequestOperationCall<TReq, TResp>;
using TBase::GetProtoRequest;
using TBase::GetPeerMetaValues;
+ using NPerms = NKikimr::TEvTicketParser::TEvAuthorizeTicket;
- const TVector<TString>& Permissions;
+ const std::function<TVector<NPerms::TPermission>(const TReq&)>& Permissions;
TVector<TString> Sids;
TGrpcYqRequestOperationCall(NGrpc::IRequestContextBase* ctx,
- void (*cb)(std::unique_ptr<IRequestOpCtx>, const IFacilityProvider&),
- const TVector<TString>& permissions)
+ void (*cb)(std::unique_ptr<IRequestOpCtx>, const IFacilityProvider&),
+ const std::function<TVector<NPerms::TPermission>(const TReq&)>& permissions)
: TGrpcRequestOperationCall<TReq, TResp>(ctx, cb, {}), Permissions(permissions) {
}
bool TryCustomAttributeProcess(const TSchemeBoardEvents::TDescribeSchemeResult& , ICheckerIface* iface) override {
-
const TString scope = GetPeerMetaValues("x-yq-scope").GetOrElse("");
if (scope.StartsWith("yandexcloud://")) {
const TVector<TString> path = StringSplitter(scope).Split('/').SkipEmpty();
if (path.size() == 2 || path.size() == 3) {
const TString& folderId = path.back();
+ const auto& permissions = Permissions(*GetProtoRequest());
TVector<TEvTicketParser::TEvAuthorizeTicket::TEntry> entries {{
- Permissions,
+ permissions,
{
{"folder_id", folderId},
{"database_id", "db"}
}
}};
- std::transform(Permissions.begin(), Permissions.end(), std::back_inserter(Sids),
- [](const TString& s) -> TString { return s + "@as"; });
+ std::transform(permissions.begin(), permissions.end(), std::back_inserter(Sids),
+ [](const auto& s) -> TString { return s.Permission + "@as"; });
auto serviceAccountId = NYq::ExtractServiceAccountId(*GetProtoRequest());
if (serviceAccountId) {
entries.push_back({
- {"iam.serviceAccounts.use"},
+ {{NPerms::Required("iam.serviceAccounts.use")}},
{
{"service_account_id", serviceAccountId},
{"database_id", "db"}
@@ -61,7 +61,7 @@ public:
return true;
}
}
-
+
return false;
}
};
diff --git a/ydb/core/security/ticket_parser.cpp b/ydb/core/security/ticket_parser.cpp
index c7d024d03dc..5654a8310b7 100644
--- a/ydb/core/security/ticket_parser.cpp
+++ b/ydb/core/security/ticket_parser.cpp
@@ -136,7 +136,7 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
if (it != entry.Permissions.begin()) {
key << '-';
}
- key << *it;
+ key << it->Permission << "(" << it->Required << ")";
}
}
return key.Str();
diff --git a/ydb/services/yq/grpc_service.cpp b/ydb/services/yq/grpc_service.cpp
index bb71dde0926..69a20ecccd3 100644
--- a/ydb/services/yq/grpc_service.cpp
+++ b/ydb/services/yq/grpc_service.cpp
@@ -35,113 +35,199 @@ void TGRpcYandexQueryService::DecRequest() {
void TGRpcYandexQueryService::SetupIncomingRequests(NGrpc::TLoggerPtr logger) {
auto getCounterBlock = CreateCounterCb(Counters_, ActorSystem_);
- static const TVector<TString> CreateQueryPermissions = {
- "yq.queries.create",
- "yq.queries.invoke",
- "yq.connections.use",
- "yq.bindings.use",
- "yq.resources.managePublic"
- };
- static const TVector<TString> ListQueriesPermissions = {
- "yq.queries.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> DescribeQueryPermissions = {
- "yq.queries.get",
- "yq.queries.viewAst",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> GetQueryStatusPermissions = {
- "yq.queries.getStatus",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> ModifyQueryPermissions = {
- "yq.queries.update",
- "yq.queries.invoke",
- "yq.connections.use",
- "yq.bindings.use",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
- static const TVector<TString> DeleteQueryPermissions = {
- "yq.queries.delete",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
- static const TVector<TString> ControlQueryPermissions = {
- "yq.queries.control",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
- static const TVector<TString> GetResultDataPermissions = {
- "yq.queries.getData",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> ListJobsPermissions = {
- "yq.jobs.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> DescribeJobPermissions = {
- "yq.jobs.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> CreateConnectionPermissions = {
- "yq.connections.create",
- "yq.resources.managePublic",
- };
- static const TVector<TString> ListConnectionsPermissions = {
- "yq.connections.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> DescribeConnectionPermissions = {
- "yq.connections.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> ModifyConnectionPermissions = {
- "yq.connections.update",
- "yq.resources.managePublic",
- "yq.resources.managePrivate",
- };
- static const TVector<TString> DeleteConnectionPermissions = {
- "yq.connections.delete",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
- static const TVector<TString> TestConnectionPermissions = {
- "yq.connections.create",
- };
- static const TVector<TString> CreateBindingPermissions = {
- "yq.bindings.create",
- "yq.resources.managePublic"
- };
- static const TVector<TString> ListBindingsPermissions = {
- "yq.bindings.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> DescribeBindingPermissions = {
- "yq.bindings.get",
- "yq.resources.viewPublic",
- "yq.resources.viewPrivate"
- };
- static const TVector<TString> ModifyBindingPermissions = {
- "yq.bindings.update",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
- static const TVector<TString> DeleteBindingPermissions = {
- "yq.bindings.delete",
- "yq.resources.managePublic",
- "yq.resources.managePrivate"
- };
+ using NPerms = NKikimr::TEvTicketParser::TEvAuthorizeTicket;
+
+ static const std::function CreateQueryPermissions{[](const YandexQuery::CreateQueryRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.queries.create"),
+ NPerms::Optional("yq.connections.use"),
+ NPerms::Optional("yq.bindings.use")
+ };
+ if (request.execute_mode() != YandexQuery::SAVE) {
+ permissions.push_back(NPerms::Required("yq.queries.invoke"));
+ }
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function ListQueriesPermissions{[](const YandexQuery::ListQueriesRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function DescribeQueryPermissions{[](const YandexQuery::DescribeQueryRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.get"),
+ NPerms::Optional("yq.queries.viewAst"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function GetQueryStatusPermissions{[](const YandexQuery::GetQueryStatusRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.getStatus"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function ModifyQueryPermissions{[](const YandexQuery::ModifyQueryRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.queries.update"),
+ NPerms::Optional("yq.connections.use"),
+ NPerms::Optional("yq.bindings.use"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ if (request.execute_mode() != YandexQuery::SAVE) {
+ permissions.push_back(NPerms::Required("yq.queries.invoke"));
+ }
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function DeleteQueryPermissions{[](const YandexQuery::DeleteQueryRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.delete"),
+ NPerms::Optional("yq.resources.managePublic"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ }};
+
+ static const std::function ControlQueryPermissions{[](const YandexQuery::ControlQueryRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.control"),
+ NPerms::Optional("yq.resources.managePublic"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ }};
+
+ static const std::function GetResultDataPermissions{[](const YandexQuery::GetResultDataRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.queries.getData"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function ListJobsPermissions{[](const YandexQuery::ListJobsRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.jobs.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function DescribeJobPermissions{[](const YandexQuery::DescribeJobRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.jobs.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function CreateConnectionPermissions{[](const YandexQuery::CreateConnectionRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.connections.create"),
+ };
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function ListConnectionsPermissions{[](const YandexQuery::ListConnectionsRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.connections.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function DescribeConnectionPermissions{[](const YandexQuery::DescribeConnectionRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.connections.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function ModifyConnectionPermissions{[](const YandexQuery::ModifyConnectionRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.connections.update"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function DeleteConnectionPermissions{[](const YandexQuery::DeleteConnectionRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.connections.delete"),
+ NPerms::Optional("yq.resources.managePublic"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ }};
+
+ static const std::function TestConnectionPermissions{[](const YandexQuery::TestConnectionRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.connections.create")
+ };
+ }};
+
+ static const std::function CreateBindingPermissions{[](const YandexQuery::CreateBindingRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.bindings.create"),
+ };
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function ListBindingsPermissions{[](const YandexQuery::ListBindingsRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.bindings.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function DescribeBindingPermissions{[](const YandexQuery::DescribeBindingRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.bindings.get"),
+ NPerms::Optional("yq.resources.viewPublic"),
+ NPerms::Optional("yq.resources.viewPrivate")
+ };
+ }};
+
+ static const std::function ModifyBindingPermissions{[](const YandexQuery::ModifyBindingRequest& request) {
+ TVector<NPerms::TPermission> permissions{
+ NPerms::Required("yq.bindings.update"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ if (request.content().acl().visibility() == YandexQuery::Acl::SCOPE) {
+ permissions.push_back(NPerms::Required("yq.resources.managePublic"));
+ }
+ return permissions;
+ }};
+
+ static const std::function DeleteBindingPermissions{[](const YandexQuery::DeleteBindingRequest&) -> TVector<NPerms::TPermission> {
+ return {
+ NPerms::Required("yq.bindings.delete"),
+ NPerms::Optional("yq.resources.managePublic"),
+ NPerms::Optional("yq.resources.managePrivate")
+ };
+ }};
#ifdef ADD_REQUEST
#error ADD_REQUEST macro already defined