diff options
author | molotkov-and <molotkov-and@yandex-team.com> | 2022-09-26 15:13:18 +0300 |
---|---|---|
committer | molotkov-and <molotkov-and@yandex-team.com> | 2022-09-26 15:13:18 +0300 |
commit | 823faff51b40346fc056bf0c3c26fe8969ccbc44 (patch) | |
tree | 46051f357415674565b7f12dcd57ac7c7aeac788 | |
parent | 94c11243bb91cb213c3ad688d235beeb1c9eab73 (diff) | |
download | ydb-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.cpp | 79 | ||||
-rw-r--r-- | ydb/core/security/ticket_parser_impl.h | 83 |
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) { |