Skip to content

Commit

Permalink
Add test to check restore lockout parameters from local db
Browse files Browse the repository at this point in the history
  • Loading branch information
molotkov-and committed Jan 15, 2025
1 parent b946059 commit 77429a3
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 54 deletions.
80 changes: 33 additions & 47 deletions ydb/core/tx/schemeshard/ut_login/ut_login.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,6 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
}

// User is blocked for 3 seconds
// runtime.AdvanceCurrentTime(TDuration::Minutes(61));
Sleep(TDuration::Seconds(4));

resultLogin = Login(runtime, "user1", "wrongpassword6");
Expand Down Expand Up @@ -702,7 +701,6 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
}

// FailedAttemptCount will reset in 3 seconds
// runtime.AdvanceCurrentTime(TDuration::Minutes(61));
Sleep(TDuration::Seconds(4));

// FailedAttemptCount should be reset
Expand Down Expand Up @@ -752,10 +750,9 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
}

// user is blocked for 3 seconds
// runtime.AdvanceCurrentTime(TDuration::Minutes(61));
Sleep(TDuration::Seconds(4));

// Unlock user after 1 hour
// Unlock user after 3 seconds
resultLogin = Login(runtime, "user1", "password1");
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");

Expand Down Expand Up @@ -784,14 +781,12 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
}

// user2 is blocked for 7 seconds
// After 3 hours user2 must be locked out
// runtime.AdvanceCurrentTime(TDuration::Hours(3));
// After 4 seconds user2 must be locked out
Sleep(TDuration::Seconds(4));
resultLogin = Login(runtime, "user2", "wrongpassword28");
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user2 is locked out");

// After 8 seconds user2 must be unlocked
// runtime.AdvanceCurrentTime(TDuration::Minutes(5 * 60 + 1));
// After 7 seconds user2 must be unlocked
Sleep(TDuration::Seconds(8));

// Unlock user after 7 sec
Expand Down Expand Up @@ -829,7 +824,14 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user1 is locked out");
}

void CheckUserIsLockedOutPermanently(TTestBasicRuntime& runtime) {
Y_UNIT_TEST(CheckThatLockedOutParametersIsRestoredFromLocalDb) {
TTestBasicRuntime runtime;
runtime.AddAppDataInit([] (ui32 nodeIdx, NKikimr::TAppData& appData) {
Y_UNUSED(nodeIdx);
auto accountLockout = appData.AuthConfig.MutableAccountLockout();
accountLockout->SetAttemptThreshold(4);
accountLockout->SetAttemptResetDuration("3s");
});
TTestEnv env(runtime);
auto accountLockoutConfig = runtime.GetAppData().AuthConfig.GetAccountLockout();
ui64 txId = 100;
Expand All @@ -840,63 +842,47 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
}

CreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user1", "password1");
// Make 2 failed login attempts
NKikimrScheme::TEvLoginResult resultLogin;
for (size_t attempt = 0; attempt < accountLockoutConfig.GetAttemptThreshold(); attempt++) {
for (size_t attempt = 0; attempt < accountLockoutConfig.GetAttemptThreshold() / 2; attempt++) {
resultLogin = Login(runtime, "user1", TStringBuilder() << "wrongpassword" << attempt);
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "Invalid password");
}
resultLogin = Login(runtime, "user1", TStringBuilder() << "wrongpassword" << accountLockoutConfig.GetAttemptThreshold());
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user1 is locked out");

// Also do not accept correct password
resultLogin = Login(runtime, "user1", "password1");
TActorId sender = runtime.AllocateEdgeActor();
RebootTablet(runtime, TTestTxConfig::SchemeShard, sender);

// After reboot schemeshard user has only 2 attempts to successful login before lock out
for (size_t attempt = 0; attempt < accountLockoutConfig.GetAttemptThreshold() / 2; attempt++) {
resultLogin = Login(runtime, "user1", TStringBuilder() << "wrongpassword" << attempt);
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "Invalid password");
}
resultLogin = Login(runtime, "user1", TStringBuilder() << "wrongpassword" << accountLockoutConfig.GetAttemptThreshold());
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user1 is locked out");

{
auto describe = DescribePath(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
CheckSecurityState(describe, {.PublicKeysSize = 1, .SidsSize = 1});
CheckSecurityState(describe, {.PublicKeysSize = 2, .SidsSize = 1});
}

// User is blocked permanently
runtime.AdvanceCurrentTime(TDuration::Days(365));
Sleep(TDuration::Seconds(2));
RebootTablet(runtime, TTestTxConfig::SchemeShard, sender);

// After 1 year user is locked out
resultLogin = Login(runtime, "user1", "wrongpassword365");
// After reboot schemeshard user1 must be locked out
resultLogin = Login(runtime, "user1", TStringBuilder() << "wrongpassword" << accountLockoutConfig.GetAttemptThreshold());
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user1 is locked out");

// Also do not accept correct password
resultLogin = Login(runtime, "user1", "password1");
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), TStringBuilder() << "User user1 is locked out");
// User1 must be unlocked in 1 second after reboot schemeshard
Sleep(TDuration::Seconds(2));

resultLogin = Login(runtime, "user1", "password1");
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
{
auto describe = DescribePath(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
CheckSecurityState(describe, {.PublicKeysSize = 1, .SidsSize = 1});
CheckSecurityState(describe, {.PublicKeysSize = 3, .SidsSize = 1});
CheckToken(resultLogin.token(), describe, "user1");
}
}

// Incorrect tests. Login library is using std::chrono and we cannot to simulate change current time

// Y_UNIT_TEST(LockOutUserPermanentlyIfAttemptResetDurationIsZeroSeconds) {
// TTestBasicRuntime runtime;
// runtime.AddAppDataInit([] (ui32 nodeIdx, NKikimr::TAppData& appData) {
// Y_UNUSED(nodeIdx);
// auto accountLockout = appData.AuthConfig.MutableAccountLockout();
// accountLockout->SetAttemptThreshold(4);
// accountLockout->SetAttemptResetDuration("0s");
// });
// CheckUserIsLockedOutPermanently(runtime);
// }

// Y_UNIT_TEST(LockOutUserPermanentlyIfAttemptResetDurationCannotParse) {
// TTestBasicRuntime runtime;
// runtime.AddAppDataInit([] (ui32 nodeIdx, NKikimr::TAppData& appData) {
// Y_UNUSED(nodeIdx);
// auto accountLockout = appData.AuthConfig.MutableAccountLockout();
// accountLockout->SetAttemptThreshold(4);
// accountLockout->SetAttemptResetDuration("blablabla");
// });
// CheckUserIsLockedOutPermanently(runtime);
// }
}

namespace NSchemeShardUT_Private {
Expand Down
7 changes: 0 additions & 7 deletions ydb/library/login/login.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,6 @@ bool TLoginProvider::ShouldResetFailedAttemptCount(const TSidRecord& sid) const
if (AccountLockout.AttemptResetDuration == std::chrono::system_clock::duration::zero()) {
return false;
}
// Cerr << "+++now: " << std::chrono::system_clock::now().time_since_epoch().count() << Endl;;
// Cerr << "+++sid.LastFailedLoginAttempt: " << sid.LastFailedLoginAttempt.time_since_epoch().count() << Endl;
// Cerr << "+++AccountLockout.AttemptResetDuration: " << AccountLockout.AttemptResetDuration.count() << Endl;
// Cerr << "+++sum: " << (sid.LastFailedLoginAttempt + AccountLockout.AttemptResetDuration).time_since_epoch().count() << Endl;
return sid.LastFailedLoginAttempt + AccountLockout.AttemptResetDuration < std::chrono::system_clock::now();
}

Expand All @@ -365,9 +361,7 @@ TLoginProvider::TCheckLockOutResponse TLoginProvider::CheckLockOutUser(const TCh

TSidRecord& sid = itUser->second;
if (CheckLockout(sid)) {
// Cerr << "+++CheckLockout: true" << Endl;
if (ShouldUnlockAccount(sid)) {
// Cerr << "+++UnlockAccount" << Endl;
UnlockAccount(&sid);
response.Status = TCheckLockOutResponse::EStatus::RESET;
} else {
Expand All @@ -376,7 +370,6 @@ TLoginProvider::TCheckLockOutResponse TLoginProvider::CheckLockOutUser(const TCh
}
return response;
} else if (ShouldResetFailedAttemptCount(sid)) {
// Cerr << "+++CheckLockout: false" << Endl;
ResetFailedLoginAttemptCount(&sid);
response.Status = TCheckLockOutResponse::EStatus::RESET;
return response;
Expand Down

0 comments on commit 77429a3

Please sign in to comment.