1
+ #include " schemeshard_impl.h"
2
+ #include < ydb/library/login/login.h>
1
3
#include < ydb/library/security/util.h>
2
4
#include < ydb/core/protos/auth.pb.h>
3
5
#include < ydb/core/base/auth.h>
4
6
#include < ydb/core/base/local_user_token.h>
5
7
6
- #include " schemeshard_impl.h"
7
-
8
8
namespace NKikimr {
9
9
namespace NSchemeShard {
10
10
11
- using namespace NTabletFlatExecutor ;
12
-
13
11
struct TSchemeShard ::TTxLogin : TSchemeShard::TRwTxBase {
14
12
TEvSchemeShard::TEvLogin::TPtr Request;
15
13
TPathId SubDomainPathId;
16
14
bool NeedPublishOnComplete = false ;
17
- THolder<TEvSchemeShard::TEvLoginResult> Result = MakeHolder<TEvSchemeShard::TEvLoginResult>() ;
15
+ TString ErrMessage ;
18
16
19
17
TTxLogin (TSelf *self, TEvSchemeShard::TEvLogin::TPtr &ev)
20
18
: TRwTxBase(self)
@@ -43,35 +41,41 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
43
41
<< " at schemeshard: " << Self->TabletID ());
44
42
NIceDb::TNiceDb db (txc.DB );
45
43
if (Self->LoginProvider .IsItTimeToRotateKeys ()) {
46
- LOG_DEBUG_S (ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, " TTxLogin RotateKeys at schemeshard: " << Self->TabletID ());
47
- std::vector<ui64> keysExpired;
48
- std::vector<ui64> keysAdded;
49
- Self->LoginProvider .RotateKeys (keysExpired, keysAdded);
50
- SubDomainPathId = Self->GetCurrentSubDomainPathId ();
51
- TSubDomainInfo::TPtr domainPtr = Self->ResolveDomainInfo (SubDomainPathId);
52
-
53
- // TODO(xenoxeno): optimize security state changes
54
- domainPtr->UpdateSecurityState (Self->LoginProvider .GetSecurityState ());
55
- domainPtr->IncSecurityStateVersion ();
56
-
57
-
58
- Self->PersistSubDomainSecurityStateVersion (db, SubDomainPathId, *domainPtr);
44
+ RotateKeys (ctx, db);
45
+ NeedPublishOnComplete = true ;
46
+ }
59
47
60
- for (ui64 keyId : keysExpired) {
61
- db.Table <Schema::LoginKeys>().Key (keyId).Delete ();
62
- }
63
- for (ui64 keyId : keysAdded) {
64
- const auto * key = Self->LoginProvider .FindKey (keyId);
65
- if (key) {
66
- db.Table <Schema::LoginKeys>().Key (keyId).Update <Schema::LoginKeys::KeyDataPEM, Schema::LoginKeys::ExpiresAt>(
67
- key->PublicKey , ToInstant (key->ExpiresAt ).MilliSeconds ());
68
- }
48
+ const auto & loginRequest = GetLoginRequest ();
49
+ if (!loginRequest.ExternalAuth ) {
50
+ if (!AppData (ctx)->AuthConfig .GetEnableLoginAuthentication ()) {
51
+ ErrMessage = " Login authentication is disabled" ;
52
+ } else {
53
+ CheckLockOutUserAndSetErrorIfAny (loginRequest.User , db);
69
54
}
55
+ }
70
56
71
- NeedPublishOnComplete = true ;
57
+ if (ErrMessage) {
58
+ SendError ();
59
+ return ;
72
60
}
73
61
74
- LoginAttempt (db, ctx);
62
+ NLogin::TLoginProvider::TLoginUserResponse Response;
63
+ TString passwordHash;
64
+ if (Self->LoginProvider .NeedVerifyHash (loginRequest, &Response, &passwordHash)) {
65
+ ctx.Send (
66
+ Self->LoginHelper ,
67
+ MakeHolder<TEvPrivate::TEvVerifyPassword>(loginRequest, Response, Request->Sender , passwordHash),
68
+ 0 ,
69
+ Request->Cookie
70
+ );
71
+ } else {
72
+ ctx.Send (
73
+ Self->SelfId (),
74
+ MakeHolder<TEvPrivate::TEvLoginFinalize>(loginRequest, Response, Request->Sender , " " , /* needUpdateCache*/ false ),
75
+ 0 ,
76
+ Request->Cookie
77
+ );
78
+ }
75
79
}
76
80
77
81
void DoComplete (const TActorContext &ctx) override {
@@ -81,96 +85,67 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
81
85
82
86
LOG_DEBUG_S (ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
83
87
" TTxLogin Complete"
84
- << " , result: " << Result-> Record . ShortDebugString ( )
88
+ << " , with " << (ErrMessage ? " error: " + ErrMessage : " no errors " )
85
89
<< " , at schemeshard: " << Self->TabletID ());
86
-
87
- ctx.Send (Request->Sender , std::move (Result), 0 , Request->Cookie );
88
- }
90
+ }
89
91
90
92
private:
91
- bool IsAdmin () const {
92
- const auto & user = Request->Get ()->Record .GetUser ();
93
- const auto userToken = NKikimr::BuildLocalUserToken (Self->LoginProvider , user);
94
- return IsAdministrator (AppData (), &userToken);
95
- }
96
-
97
- void LoginAttempt (NIceDb::TNiceDb& db, const TActorContext& ctx) {
98
- const auto & loginRequest = GetLoginRequest ();
99
- if (!loginRequest.ExternalAuth && !AppData (ctx)->AuthConfig .GetEnableLoginAuthentication ()) {
100
- Result->Record .SetError (" Login authentication is disabled" );
101
- return ;
102
- }
103
- if (loginRequest.ExternalAuth ) {
104
- HandleExternalAuth (loginRequest);
105
- } else {
106
- HandleLoginAuth (loginRequest, db);
107
- }
108
- }
109
-
110
- void HandleExternalAuth (const NLogin::TLoginProvider::TLoginUserRequest& loginRequest) {
111
- const NLogin::TLoginProvider::TLoginUserResponse loginResponse = Self->LoginProvider .LoginUser (loginRequest);
112
- switch (loginResponse.Status ) {
113
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
114
- Result->Record .SetToken (loginResponse.Token );
115
- Result->Record .SetSanitizedToken (loginResponse.SanitizedToken );
116
- Result->Record .SetIsAdmin (IsAdmin ());
117
- break ;
118
- }
119
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD:
120
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
121
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
122
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
123
- Result->Record .SetError (loginResponse.Error );
124
- break ;
93
+ void RotateKeys (const TActorContext& ctx, NIceDb::TNiceDb& db) {
94
+ LOG_DEBUG_S (ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, " TTxLogin RotateKeys at schemeshard: " << Self->TabletID ());
95
+ std::vector<ui64> keysExpired;
96
+ std::vector<ui64> keysAdded;
97
+ Self->LoginProvider .RotateKeys (keysExpired, keysAdded);
98
+ SubDomainPathId = Self->GetCurrentSubDomainPathId ();
99
+ TSubDomainInfo::TPtr domainPtr = Self->ResolveDomainInfo (SubDomainPathId);
100
+
101
+ // TODO(xenoxeno): optimize security state changes
102
+ domainPtr->UpdateSecurityState (Self->LoginProvider .GetSecurityState ());
103
+ domainPtr->IncSecurityStateVersion ();
104
+
105
+ Self->PersistSubDomainSecurityStateVersion (db, SubDomainPathId, *domainPtr);
106
+
107
+ for (ui64 keyId : keysExpired) {
108
+ db.Table <Schema::LoginKeys>().Key (keyId).Delete ();
125
109
}
110
+ for (ui64 keyId : keysAdded) {
111
+ const auto * key = Self->LoginProvider .FindKey (keyId);
112
+ if (key) {
113
+ db.Table <Schema::LoginKeys>().Key (keyId).Update <Schema::LoginKeys::KeyDataPEM, Schema::LoginKeys::ExpiresAt>(
114
+ key->PublicKey , ToInstant (key->ExpiresAt ).MilliSeconds ());
115
+ }
126
116
}
127
117
}
128
118
129
- void HandleLoginAuth (const NLogin::TLoginProvider::TLoginUserRequest& loginRequest , NIceDb::TNiceDb& db) {
119
+ void CheckLockOutUserAndSetErrorIfAny (const TString& user , NIceDb::TNiceDb& db) {
130
120
using namespace NLogin ;
131
- const TLoginProvider::TCheckLockOutResponse checkLockOutResponse = Self->LoginProvider .CheckLockOutUser ({.User = loginRequest. User });
121
+ const TLoginProvider::TCheckLockOutResponse checkLockOutResponse = Self->LoginProvider .CheckLockOutUser ({.User = user });
132
122
switch (checkLockOutResponse.Status ) {
133
123
case TLoginProvider::TCheckLockOutResponse::EStatus::SUCCESS:
134
124
case TLoginProvider::TCheckLockOutResponse::EStatus::INVALID_USER: {
135
- Result-> Record . SetError ( checkLockOutResponse.Error ) ;
125
+ ErrMessage = checkLockOutResponse.Error ;
136
126
return ;
137
127
}
138
128
case TLoginProvider::TCheckLockOutResponse::EStatus::RESET: {
139
- const auto & sid = Self->LoginProvider .Sids [loginRequest. User ];
140
- db.Table <Schema::LoginSids>().Key (loginRequest. User ).Update <Schema::LoginSids::FailedAttemptCount>(sid.FailedLoginAttemptCount );
129
+ const auto & sid = Self->LoginProvider .Sids [user ];
130
+ db.Table <Schema::LoginSids>().Key (user ).Update <Schema::LoginSids::FailedAttemptCount>(sid.FailedLoginAttemptCount );
141
131
break ;
142
132
}
143
133
case TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED:
144
134
case TLoginProvider::TCheckLockOutResponse::EStatus::UNSPECIFIED: {
145
135
break ;
146
136
}
147
137
}
138
+ }
148
139
149
- const TLoginProvider::TLoginUserResponse loginResponse = Self->LoginProvider .LoginUser (loginRequest);
150
- switch (loginResponse.Status ) {
151
- case TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
152
- const auto & sid = Self->LoginProvider .Sids [loginRequest.User ];
153
- db.Table <Schema::LoginSids>().Key (loginRequest.User ).Update <Schema::LoginSids::LastSuccessfulAttempt,
154
- Schema::LoginSids::FailedAttemptCount>(ToMicroSeconds (sid.LastSuccessfulLogin ), sid.FailedLoginAttemptCount );
155
- Result->Record .SetToken (loginResponse.Token );
156
- Result->Record .SetSanitizedToken (loginResponse.SanitizedToken );
157
- Result->Record .SetIsAdmin (IsAdmin ());
158
- break ;
159
- }
160
- case TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD: {
161
- const auto & sid = Self->LoginProvider .Sids [loginRequest.User ];
162
- db.Table <Schema::LoginSids>().Key (loginRequest.User ).Update <Schema::LoginSids::LastFailedAttempt,
163
- Schema::LoginSids::FailedAttemptCount>(ToMicroSeconds (sid.LastFailedLogin ), sid.FailedLoginAttemptCount );
164
- Result->Record .SetError (loginResponse.Error );
165
- break ;
166
- }
167
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
168
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
169
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
170
- Result->Record .SetError (loginResponse.Error );
171
- break ;
172
- }
173
- }
140
+ void SendError () {
141
+ THolder<TEvSchemeShard::TEvLoginResult> result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
142
+ result->Record .SetError (ErrMessage);
143
+ Self->Send (
144
+ Request->Sender ,
145
+ std::move (result),
146
+ 0 ,
147
+ Request->Cookie
148
+ );
174
149
}
175
150
};
176
151
0 commit comments