aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormolotkov-and <molotkov-and@yandex-team.com>2022-09-23 14:08:35 +0300
committermolotkov-and <molotkov-and@yandex-team.com>2022-09-23 14:08:35 +0300
commit07c943de4adb7d76d1a1725b6c5b9d9b9edf7733 (patch)
tree92f1b4af6a5fd101626b2004ca2ccd335431e1b9
parent9ce5be3812d329e848be6de9ce89d693860a811d (diff)
downloadydb-07c943de4adb7d76d1a1725b6c5b9d9b9edf7733.tar.gz
Extract common source code from ticket parsers to separate class
-rw-r--r--ydb/core/security/ticket_parser.cpp171
-rw-r--r--ydb/core/security/ticket_parser.h3
-rw-r--r--ydb/core/security/ticket_parser_impl.h172
3 files changed, 182 insertions, 164 deletions
diff --git a/ydb/core/security/ticket_parser.cpp b/ydb/core/security/ticket_parser.cpp
index 6e2121e15e..c373f8f5a9 100644
--- a/ydb/core/security/ticket_parser.cpp
+++ b/ydb/core/security/ticket_parser.cpp
@@ -1,43 +1,19 @@
-#include <library/cpp/actors/core/actorsystem.h>
#include <library/cpp/actors/core/log.h>
-#include <library/cpp/actors/core/actor_bootstrapped.h>
#include <library/cpp/actors/core/hfunc.h>
#include <library/cpp/digest/md5/md5.h>
-#include <library/cpp/openssl/init/init.h>
-#include <library/cpp/string_utils/base64/base64.h>
-#include <ydb/core/base/appdata.h>
#include <ydb/core/base/counters.h>
#include <ydb/core/mon/mon.h>
#include <ydb/library/security/util.h>
-#include <util/generic/queue.h>
-#include <util/generic/deque.h>
-#include <util/stream/file.h>
#include <util/string/vector.h>
+#include "ticket_parser_impl.h"
#include "ticket_parser.h"
namespace NKikimr {
-class TTicketParser : public TActorBootstrapped<TTicketParser> {
+class TTicketParser : public TTicketParserImpl<TTicketParser> {
using TThis = TTicketParser;
- using TBase = TActorBootstrapped<TTicketParser>;
-
- NKikimrProto::TAuthConfig Config;
- TString DomainName;
-
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsReceived;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsSuccess;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrors;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrorsRetryable;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrorsPermanent;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsBuiltin;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsLogin;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsCacheHit;
- ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsCacheMiss;
- NMonitoring::THistogramPtr CounterTicketsBuildTime;
-
- TDuration RefreshPeriod = TDuration::Seconds(1); // how often do we check for ticket freshness/expiration
- TDuration LifeTime = TDuration::Hours(1); // for how long ticket will remain in the cache after last access
- TDuration ExpireTime = TDuration::Hours(24); // after what time ticket will expired and removed from cache
+ using TBase = TTicketParserImpl<TTicketParser>;
+ using TBase::TBase;
enum class ETokenType {
Unknown,
@@ -46,7 +22,7 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
Login,
};
- ETokenType ParseTokenType(TStringBuf tokenType) {
+ ETokenType ParseTokenType(const TStringBuf& tokenType) const {
if (tokenType == "Login") {
if (UseLoginProvider) {
return ETokenType::Login;
@@ -57,37 +33,15 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
return ETokenType::Unknown;
}
- struct TTokenRecord {
- TTokenRecord(const TTokenRecord&) = delete;
- TTokenRecord& operator =(const TTokenRecord&) = delete;
-
- TString Ticket;
- TString Subject; // login
- TEvTicketParser::TError Error;
- TIntrusivePtr<NACLib::TUserToken> Token;
- TString SerializedToken;
- TDeque<THolder<TEventHandle<TEvTicketParser::TEvAuthorizeTicket>>> AuthorizeRequests;
- ui64 ResponsesLeft = 0;
- TInstant InitTime;
- TInstant ExpireTime;
- TInstant AccessTime;
+ struct TTokenRecord : TBase::TTokenRecordBase {
+ using TBase::TTokenRecordBase::TTokenRecordBase;
+
ETokenType TokenType = ETokenType::Unknown;
- TString PeerName;
- TString Database;
- TStackVec<TString> AdditionalSIDs;
TString GetSubject() const {
return Subject;
}
- TTokenRecord(TStringBuf ticket)
- : Ticket(ticket)
- {}
-
- bool IsTokenReady() const {
- return Token != nullptr;
- }
-
TString GetAuthType() const {
switch (TokenType) {
case ETokenType::Unknown:
@@ -102,66 +56,10 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
}
};
- struct TTokenRefreshRecord {
- TString Key;
- TInstant RefreshTime;
-
- bool operator <(const TTokenRefreshRecord& o) const {
- return RefreshTime > o.RefreshTime;
- }
- };
-
THashMap<TString, TTokenRecord> UserTokens;
- TPriorityQueue<TTokenRefreshRecord> RefreshQueue;
- std::unordered_map<TString, NLogin::TLoginProvider> LoginProviders;
- bool UseLoginProvider = false;
static TString GetKey(TEvTicketParser::TEvAuthorizeTicket* request) {
- TStringStream key;
- key << request->Ticket;
- key << ':';
- if (request->Database) {
- key << request->Database;
- key << ':';
- }
- for (const auto& entry : request->Entries) {
- for (auto it = entry.Attributes.begin(); it != entry.Attributes.end(); ++it) {
- if (it != entry.Attributes.begin()) {
- key << '-';
- }
- key << it->second;
- }
- key << ':';
- for (auto it = entry.Permissions.begin(); it != entry.Permissions.end(); ++it) {
- if (it != entry.Permissions.begin()) {
- key << '-';
- }
- key << it->Permission << "(" << it->Required << ")";
- }
- }
- return key.Str();
- }
-
- static TStringBuf GetTicketFromKey(TStringBuf key) {
- return key.Before(':');
- }
-
- TInstant GetExpireTime(TInstant now) {
- return now + ExpireTime;
- }
-
- TDuration GetLifeTime() {
- return LifeTime;
- }
-
- static void EnrichUserTokenWithBuiltins(const TTokenRecord& tokenRecord) {
- const TString& allAuthenticatedUsers = AppData()->AllAuthenticatedUsers;
- if (!allAuthenticatedUsers.empty()) {
- tokenRecord.Token->AddGroupSID(allAuthenticatedUsers);
- }
- for (const TString& sid : tokenRecord.AdditionalSIDs) {
- tokenRecord.Token->AddGroupSID(sid);
- }
+ return request->Ticket + TBase::GetKey(request);
}
void InitTokenRecord(const TString& key, TTokenRecord& record, const TActorContext& ctx) {
@@ -285,28 +183,6 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
RefreshQueue.push({key, record.ExpireTime});
}
- void Respond(TTokenRecord& record, const TActorContext& ctx) {
- if (record.IsTokenReady()) {
- for (const auto& request : record.AuthorizeRequests) {
- ctx.Send(request->Sender, new TEvTicketParser::TEvAuthorizeTicketResult(record.Ticket, record.Token, record.SerializedToken), 0, request->Cookie);
- }
- } else {
- for (const auto& request : record.AuthorizeRequests) {
- ctx.Send(request->Sender, new TEvTicketParser::TEvAuthorizeTicketResult(record.Ticket, record.Error), 0, request->Cookie);
- }
- }
- record.AuthorizeRequests.clear();
- }
-
- void CrackTicket(const TString& ticketBody, TStringBuf& ticket, TStringBuf& ticketType) {
- ticket = ticketBody;
- ticketType = ticket.NextTok(' ');
- if (ticket.empty()) {
- ticket = ticketBody;
- ticketType.Clear();
- }
- }
-
void Handle(TEvTicketParser::TEvAuthorizeTicket::TPtr& ev, const TActorContext& ctx) {
TStringBuf ticket;
TStringBuf ticketType;
@@ -388,24 +264,6 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
UserTokens.erase(ev->Get()->Ticket);
}
- static TString GetLoginProviderKeys(const NLogin::TLoginProvider& loginProvider) {
- TStringBuilder keys;
- for (const auto& [key, pubKey, privKey, expiresAt] : loginProvider.Keys) {
- if (!keys.empty()) {
- keys << ",";
- }
- keys << key;
- }
- return keys;
- }
-
- void Handle(TEvTicketParser::TEvUpdateLoginSecurityState::TPtr& ev, const TActorContext& ctx) {
- auto& loginProvider = LoginProviders[ev->Get()->SecurityState.GetAudience()];
- loginProvider.UpdateSecurityState(ev->Get()->SecurityState);
- LOG_DEBUG_S(ctx, NKikimrServices::TICKET_PARSER,
- "Updated state for " << loginProvider.Audience << " keys " << GetLoginProviderKeys(loginProvider));
- }
-
void HandleRefresh(const NActors::TActorContext& ctx) {
while (!RefreshQueue.empty() && RefreshQueue.top().RefreshTime <= ctx.Now()) {
TString key = RefreshQueue.top().Key;
@@ -429,10 +287,6 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
ctx.Schedule(RefreshPeriod, new NActors::TEvents::TEvWakeup());
}
- static TStringBuf HtmlBool(bool v) {
- return v ? "<span style='font-weight:bold'>&#x2611;</span>" : "<span style='font-weight:bold'>&#x2610;</span>";
- }
-
void Handle(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx) {
const auto& params = ev->Get()->Request.GetParams();
TStringBuilder html;
@@ -565,14 +419,12 @@ class TTicketParser : public TActorBootstrapped<TTicketParser> {
}
public:
- static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::TICKET_PARSER_ACTOR; }
-
void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext& ctx) {
switch (ev->GetTypeRewrite()) {
HFunc(TEvTicketParser::TEvAuthorizeTicket, Handle);
HFunc(TEvTicketParser::TEvRefreshTicket, Handle);
HFunc(TEvTicketParser::TEvDiscardTicket, Handle);
- HFunc(TEvTicketParser::TEvUpdateLoginSecurityState, Handle);
+ HFunc(TEvTicketParser::TEvUpdateLoginSecurityState, TBase::Handle);
HFunc(NMon::TEvHttpInfo, Handle);
CFunc(TEvents::TSystem::Wakeup, HandleRefresh);
CFunc(TEvents::TSystem::PoisonPill, Die);
@@ -615,9 +467,6 @@ public:
ctx.Schedule(RefreshPeriod, new NActors::TEvents::TEvWakeup());
TBase::Become(&TThis::StateWork);
}
-
- TTicketParser(const NKikimrProto::TAuthConfig& authConfig)
- : Config(authConfig) {}
};
IActor* CreateTicketParser(const NKikimrProto::TAuthConfig& authConfig) {
diff --git a/ydb/core/security/ticket_parser.h b/ydb/core/security/ticket_parser.h
index 6623ecae2a..4db4b13e97 100644
--- a/ydb/core/security/ticket_parser.h
+++ b/ydb/core/security/ticket_parser.h
@@ -1,10 +1,7 @@
#pragma once
-#include <ydb/core/base/defs.h>
-#include <ydb/core/base/events.h>
#include <ydb/core/protos/config.pb.h>
#include <ydb/core/base/ticket_parser.h>
namespace NKikimr {
IActor* CreateTicketParser(const NKikimrProto::TAuthConfig& authConfig);
}
-
diff --git a/ydb/core/security/ticket_parser_impl.h b/ydb/core/security/ticket_parser_impl.h
new file mode 100644
index 0000000000..9b8ebe72ae
--- /dev/null
+++ b/ydb/core/security/ticket_parser_impl.h
@@ -0,0 +1,172 @@
+#pragma once
+#include <library/cpp/actors/core/log.h>
+#include <library/cpp/actors/core/actor_bootstrapped.h>
+#include <ydb/core/base/appdata.h>
+#include <ydb/core/base/ticket_parser.h>
+#include <util/generic/queue.h>
+
+namespace NKikimr {
+
+template <typename T>
+class TTicketParserImpl : public TActorBootstrapped<T> {
+ using TThis = TTicketParserImpl;
+ using TBase = TActorBootstrapped<T>;
+
+protected:
+ NKikimrProto::TAuthConfig Config;
+ TString DomainName;
+
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsReceived;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsSuccess;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrors;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrorsRetryable;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsErrorsPermanent;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsBuiltin;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsLogin;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsCacheHit;
+ ::NMonitoring::TDynamicCounters::TCounterPtr CounterTicketsCacheMiss;
+ ::NMonitoring::THistogramPtr CounterTicketsBuildTime;
+
+ TDuration RefreshPeriod = TDuration::Seconds(1); // how often do we check for ticket freshness/expiration
+ TDuration LifeTime = TDuration::Hours(1); // for how long ticket will remain in the cache after last access
+ TDuration ExpireTime = TDuration::Hours(24); // after what time ticket will expired and removed from cache
+
+ struct TTokenRecordBase {
+ TTokenRecordBase(const TTokenRecordBase&) = delete;
+ TTokenRecordBase& operator =(const TTokenRecordBase&) = delete;
+
+ TString Ticket;
+ TString Subject; // login
+ TEvTicketParser::TError Error;
+ TIntrusivePtr<NACLib::TUserToken> Token;
+ TString SerializedToken;
+ TDeque<THolder<TEventHandle<TEvTicketParser::TEvAuthorizeTicket>>> AuthorizeRequests;
+ ui64 ResponsesLeft = 0;
+ TInstant InitTime;
+ TInstant ExpireTime;
+ TInstant AccessTime;
+ TString PeerName;
+ TString Database;
+ TStackVec<TString> AdditionalSIDs;
+
+ TTokenRecordBase(const TStringBuf& ticket)
+ : Ticket(ticket)
+ {}
+
+ bool IsTokenReady() const {
+ return Token != nullptr;
+ }
+ };
+
+ struct TTokenRefreshRecord {
+ TString Key;
+ TInstant RefreshTime;
+
+ bool operator <(const TTokenRefreshRecord& o) const {
+ return RefreshTime > o.RefreshTime;
+ }
+ };
+
+ TPriorityQueue<TTokenRefreshRecord> RefreshQueue;
+ std::unordered_map<TString, NLogin::TLoginProvider> LoginProviders;
+ bool UseLoginProvider = false;
+
+ static TString GetKey(TEvTicketParser::TEvAuthorizeTicket* request) {
+ TStringStream key;
+ key << ':';
+ if (request->Database) {
+ key << request->Database;
+ key << ':';
+ }
+ for (const auto& entry : request->Entries) {
+ for (auto it = entry.Attributes.begin(); it != entry.Attributes.end(); ++it) {
+ if (it != entry.Attributes.begin()) {
+ key << '-';
+ }
+ key << it->second;
+ }
+ key << ':';
+ for (auto it = entry.Permissions.begin(); it != entry.Permissions.end(); ++it) {
+ if (it != entry.Permissions.begin()) {
+ key << '-';
+ }
+ key << it->Permission << "(" << it->Required << ")";
+ }
+ }
+ return key.Str();
+ }
+
+ static TStringBuf GetTicketFromKey(TStringBuf key) {
+ return key.Before(':');
+ }
+
+ TInstant GetExpireTime(TInstant now) {
+ return now + ExpireTime;
+ }
+
+ TDuration GetLifeTime() {
+ return LifeTime;
+ }
+
+ static void EnrichUserTokenWithBuiltins(const TTokenRecordBase& tokenRecord) {
+ const TString& allAuthenticatedUsers = AppData()->AllAuthenticatedUsers;
+ if (!allAuthenticatedUsers.empty()) {
+ tokenRecord.Token->AddGroupSID(allAuthenticatedUsers);
+ }
+ for (const TString& sid : tokenRecord.AdditionalSIDs) {
+ tokenRecord.Token->AddGroupSID(sid);
+ }
+ }
+
+ void Respond(TTokenRecordBase& record, const TActorContext& ctx) {
+ if (record.IsTokenReady()) {
+ for (const auto& request : record.AuthorizeRequests) {
+ ctx.Send(request->Sender, new TEvTicketParser::TEvAuthorizeTicketResult(record.Ticket, record.Token, record.SerializedToken), 0, request->Cookie);
+ }
+ } else {
+ for (const auto& request : record.AuthorizeRequests) {
+ ctx.Send(request->Sender, new TEvTicketParser::TEvAuthorizeTicketResult(record.Ticket, record.Error), 0, request->Cookie);
+ }
+ }
+ record.AuthorizeRequests.clear();
+ }
+
+ void CrackTicket(const TString& ticketBody, TStringBuf& ticket, TStringBuf& ticketType) {
+ ticket = ticketBody;
+ ticketType = ticket.NextTok(' ');
+ if (ticket.empty()) {
+ ticket = ticketBody;
+ ticketType.Clear();
+ }
+ }
+
+ static TString GetLoginProviderKeys(const NLogin::TLoginProvider& loginProvider) {
+ TStringBuilder keys;
+ for (const auto& [key, pubKey, privKey, expiresAt] : loginProvider.Keys) {
+ if (!keys.empty()) {
+ keys << ",";
+ }
+ keys << key;
+ }
+ return keys;
+ }
+
+ void Handle(TEvTicketParser::TEvUpdateLoginSecurityState::TPtr& ev, const TActorContext& ctx) {
+ auto& loginProvider = LoginProviders[ev->Get()->SecurityState.GetAudience()];
+ loginProvider.UpdateSecurityState(ev->Get()->SecurityState);
+ LOG_DEBUG_S(ctx, NKikimrServices::TICKET_PARSER,
+ "Updated state for " << loginProvider.Audience << " keys " << GetLoginProviderKeys(loginProvider));
+ }
+
+ static TStringBuf HtmlBool(bool v) {
+ return v ? "<span style='font-weight:bold'>&#x2611;</span>" : "<span style='font-weight:bold'>&#x2610;</span>";
+ }
+
+public:
+ static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::TICKET_PARSER_ACTOR; }
+
+ TTicketParserImpl(const NKikimrProto::TAuthConfig& authConfig)
+ : Config(authConfig) {}
+};
+
+}