aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormolotkov-and <molotkov-and@yandex-team.com>2022-09-26 15:13:18 +0300
committermolotkov-and <molotkov-and@yandex-team.com>2022-09-26 15:13:18 +0300
commit823faff51b40346fc056bf0c3c26fe8969ccbc44 (patch)
tree46051f357415674565b7f12dcd57ac7c7aeac788
parent94c11243bb91cb213c3ad688d235beeb1c9eab73 (diff)
downloadydb-823faff51b40346fc056bf0c3c26fe8969ccbc44.tar.gz
Extract Authorize Ticket handle to base class
Extract Authorize Ticket handle to base class
-rw-r--r--ydb/core/security/ticket_parser.cpp79
-rw-r--r--ydb/core/security/ticket_parser_impl.h83
2 files changed, 97 insertions, 65 deletions
diff --git a/ydb/core/security/ticket_parser.cpp b/ydb/core/security/ticket_parser.cpp
index c373f8f5a9..b4439d1e12 100644
--- a/ydb/core/security/ticket_parser.cpp
+++ b/ydb/core/security/ticket_parser.cpp
@@ -15,6 +15,8 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
using TBase = TTicketParserImpl<TTicketParser>;
using TBase::TBase;
+ friend TBase;
+
enum class ETokenType {
Unknown,
Unsupported,
@@ -22,7 +24,7 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
Login,
};
- ETokenType ParseTokenType(const TStringBuf& tokenType) const {
+ ETokenType ParseTokenType(const TStringBuf tokenType) const {
if (tokenType == "Login") {
if (UseLoginProvider) {
return ETokenType::Login;
@@ -58,8 +60,18 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
THashMap<TString, TTokenRecord> UserTokens;
- static TString GetKey(TEvTicketParser::TEvAuthorizeTicket* request) {
- return request->Ticket + TBase::GetKey(request);
+ TTokenRecord* GetUserToken(const TString& key) {
+ auto it = UserTokens.find(key);
+ return it != UserTokens.end() ? &it->second : nullptr;
+ }
+
+ TTokenRecord* InsertUserToken(const TString& key, const TStringBuf ticket) {
+ auto it = UserTokens.emplace(key, ticket).first;
+ return &it->second;
+ }
+
+ static TStringStream GetKey(TEvTicketParser::TEvAuthorizeTicket* request) {
+ return request->Ticket;
}
void InitTokenRecord(const TString& key, TTokenRecord& record, const TActorContext& ctx) {
@@ -183,50 +195,11 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
RefreshQueue.push({key, record.ExpireTime});
}
- void Handle(TEvTicketParser::TEvAuthorizeTicket::TPtr& ev, const TActorContext& ctx) {
- TStringBuf ticket;
- TStringBuf ticketType;
- CrackTicket(ev->Get()->Ticket, ticket, ticketType);
-
- TString key = GetKey(ev->Get());
- TActorId sender = ev->Sender;
- ui64 cookie = ev->Cookie;
-
- CounterTicketsReceived->Inc();
- if (ticket.empty()) {
- TEvTicketParser::TError error;
- error.Message = "Ticket is empty";
- error.Retryable = false;
- LOG_ERROR_S(ctx, NKikimrServices::TICKET_PARSER, "Ticket " << MaskTicket(ticket) << ": " << error);
- ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, error), 0, cookie);
- return;
- }
- auto it = UserTokens.find(key);
- if (it != UserTokens.end()) {
- auto& record = it->second;
- // we know about token
- if (record.IsTokenReady()) {
- // token already have built
- record.AccessTime = ctx.Now();
- ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Token, record.SerializedToken), 0, cookie);
- } else if (record.Error) {
- // token stores information about previous error
- record.AccessTime = ctx.Now();
- ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Error), 0, cookie);
- } else {
- // token building in progress
- record.AuthorizeRequests.emplace_back(ev.Release());
- }
- CounterTicketsCacheHit->Inc();
- return;
- } else {
- it = UserTokens.emplace(key, ticket).first;
- CounterTicketsCacheMiss->Inc();
- }
+ bool IsTicketEmpty(const TStringBuf ticket, TEvTicketParser::TEvAuthorizeTicket::TPtr&) {
+ return ticket.empty();
+ }
- auto& record = it->second;
- record.PeerName = std::move(ev->Get()->PeerName);
- record.Database = std::move(ev->Get()->Database);
+ void SetTokenType(TTokenRecord& record, TStringBuf&, const TStringBuf ticketType) {
if (ticketType) {
record.TokenType = ParseTokenType(ticketType);
switch (record.TokenType) {
@@ -242,18 +215,6 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
break;
}
}
- InitTokenRecord(key, record, ctx);
- if (record.Error) {
- LOG_ERROR_S(ctx, NKikimrServices::TICKET_PARSER, "Ticket " << MaskTicket(ticket) << ": " << record.Error);
- ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Error), 0, cookie);
- return;
- }
- if (record.IsTokenReady()) {
- // offline check ready
- ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Token, record.SerializedToken), 0, cookie);
- return;
- }
- record.AuthorizeRequests.emplace_back(ev.Release());
}
void Handle(TEvTicketParser::TEvRefreshTicket::TPtr& ev, const TActorContext&) {
@@ -421,7 +382,7 @@ class TTicketParser : public TTicketParserImpl<TTicketParser> {
public:
void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext& ctx) {
switch (ev->GetTypeRewrite()) {
- HFunc(TEvTicketParser::TEvAuthorizeTicket, Handle);
+ HFunc(TEvTicketParser::TEvAuthorizeTicket, TBase::Handle);
HFunc(TEvTicketParser::TEvRefreshTicket, Handle);
HFunc(TEvTicketParser::TEvDiscardTicket, Handle);
HFunc(TEvTicketParser::TEvUpdateLoginSecurityState, TBase::Handle);
diff --git a/ydb/core/security/ticket_parser_impl.h b/ydb/core/security/ticket_parser_impl.h
index 9b8ebe72ae..c9e0f384a1 100644
--- a/ydb/core/security/ticket_parser_impl.h
+++ b/ydb/core/security/ticket_parser_impl.h
@@ -3,14 +3,19 @@
#include <library/cpp/actors/core/actor_bootstrapped.h>
#include <ydb/core/base/appdata.h>
#include <ydb/core/base/ticket_parser.h>
+#include <ydb/library/security/util.h>
#include <util/generic/queue.h>
namespace NKikimr {
-template <typename T>
-class TTicketParserImpl : public TActorBootstrapped<T> {
+template <typename TDerived>
+class TTicketParserImpl : public TActorBootstrapped<TDerived> {
using TThis = TTicketParserImpl;
- using TBase = TActorBootstrapped<T>;
+ using TBase = TActorBootstrapped<TDerived>;
+
+ TDerived* GetDerived() {
+ return static_cast<TDerived*>(this);
+ }
protected:
NKikimrProto::TAuthConfig Config;
@@ -49,7 +54,7 @@ protected:
TString Database;
TStackVec<TString> AdditionalSIDs;
- TTokenRecordBase(const TStringBuf& ticket)
+ TTokenRecordBase(const TStringBuf ticket)
: Ticket(ticket)
{}
@@ -72,7 +77,7 @@ protected:
bool UseLoginProvider = false;
static TString GetKey(TEvTicketParser::TEvAuthorizeTicket* request) {
- TStringStream key;
+ TStringStream key(TDerived::GetKey(request));
key << ':';
if (request->Database) {
key << request->Database;
@@ -96,7 +101,7 @@ protected:
return key.Str();
}
- static TStringBuf GetTicketFromKey(TStringBuf key) {
+ static TStringBuf GetTicketFromKey(const TStringBuf key) {
return key.Before(':');
}
@@ -140,6 +145,72 @@ protected:
}
}
+ template <typename TTokenRecord>
+ void TokenRecordSetup(TTokenRecord& record, TEvTicketParser::TEvAuthorizeTicket::TPtr& ev) {
+ record.PeerName = std::move(ev->Get()->PeerName);
+ record.Database = std::move(ev->Get()->Database);
+ }
+
+ void Handle(TEvTicketParser::TEvAuthorizeTicket::TPtr& ev, const TActorContext& ctx) {
+ TStringBuf ticket;
+ TStringBuf ticketType;
+ CrackTicket(ev->Get()->Ticket, ticket, ticketType);
+
+ TString key = GetKey(ev->Get());
+ TActorId sender = ev->Sender;
+ ui64 cookie = ev->Cookie;
+
+ CounterTicketsReceived->Inc();
+ if (GetDerived()->IsTicketEmpty(ticket, ev)) {
+ TEvTicketParser::TError error;
+ error.Message = "Ticket is empty";
+ error.Retryable = false;
+ LOG_ERROR_S(ctx, NKikimrServices::TICKET_PARSER, "Ticket " << MaskTicket(ticket) << ": " << error);
+ ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, error), 0, cookie);
+ return;
+ }
+ auto recordPtr = GetDerived()->GetUserToken(key);
+ if (recordPtr) {
+ auto& record = *recordPtr;
+ // we know about token
+ if (record.IsTokenReady()) {
+ // token already have built
+ record.AccessTime = ctx.Now();
+ ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Token, record.SerializedToken), 0, cookie);
+ } else if (record.Error) {
+ // token stores information about previous error
+ record.AccessTime = ctx.Now();
+ ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Error), 0, cookie);
+ } else {
+ // token building in progress
+ record.AuthorizeRequests.emplace_back(ev.Release());
+ }
+ CounterTicketsCacheHit->Inc();
+ return;
+ } else {
+ recordPtr = GetDerived()->InsertUserToken(key, ticket);
+ CounterTicketsCacheMiss->Inc();
+ }
+
+ auto& record = *recordPtr;
+ GetDerived()->TokenRecordSetup(record, ev);
+
+ GetDerived()->SetTokenType(record, ticket, ticketType);
+
+ GetDerived()->InitTokenRecord(key, record, ctx);
+ if (record.Error) {
+ LOG_ERROR_S(ctx, NKikimrServices::TICKET_PARSER, "Ticket " << MaskTicket(ticket) << ": " << record.Error);
+ ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Error), 0, cookie);
+ return;
+ }
+ if (record.IsTokenReady()) {
+ // offline check ready
+ ctx.Send(sender, new TEvTicketParser::TEvAuthorizeTicketResult(ev->Get()->Ticket, record.Token, record.SerializedToken), 0, cookie);
+ return;
+ }
+ record.AuthorizeRequests.emplace_back(ev.Release());
+ }
+
static TString GetLoginProviderKeys(const NLogin::TLoginProvider& loginProvider) {
TStringBuilder keys;
for (const auto& [key, pubKey, privKey, expiresAt] : loginProvider.Keys) {