summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Zaspa <[email protected]>2026-07-13 14:51:08 +0400
committerGitHub <[email protected]>2026-07-13 14:51:08 +0400
commit1cbcd27880ca8877cfd30386a2bff89dafa11a47 (patch)
treeda9c59a8ab65456d3d2be589537d1670143f9467
parentea4199e3c66d94f8a93ee71d84fcf5ccf1c31319 (diff)
Remove legacy password-hashing machinery from the login library (#46087)
-rw-r--r--ydb/core/protos/counters_schemeshard.proto4
-rw-r--r--ydb/core/security/ldap_auth_provider/ldap_auth_provider_ut.cpp71
-rw-r--r--ydb/core/security/ticket_parser_ut.cpp65
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__init.cpp7
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__login.cpp122
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__login_finalize.cpp138
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp3
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__user_hashes_migration.cpp141
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.cpp19
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.h12
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_login_helper.cpp56
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_login_helper.h13
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_private.h48
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_schema.h2
-rw-r--r--ydb/core/tx/schemeshard/ut_helpers/helpers.cpp17
-rw-r--r--ydb/core/tx/schemeshard/ut_helpers/helpers.h8
-rw-r--r--ydb/core/tx/schemeshard/ut_login/ut_login.cpp98
-rw-r--r--ydb/core/tx/schemeshard/ya.make4
-rw-r--r--ydb/library/login/cache/lru.cpp75
-rw-r--r--ydb/library/login/cache/lru.h55
-rw-r--r--ydb/library/login/cache/lru_ut.cpp173
-rw-r--r--ydb/library/login/cache/ut/ya.make9
-rw-r--r--ydb/library/login/cache/ya.make13
-rw-r--r--ydb/library/login/hashes_checker/hashes_checker.cpp33
-rw-r--r--ydb/library/login/hashes_checker/hashes_checker.h3
-rw-r--r--ydb/library/login/login.cpp225
-rw-r--r--ydb/library/login/login.h23
-rw-r--r--ydb/library/login/login_ut.cpp558
-rw-r--r--ydb/library/login/protos/login.proto2
-rw-r--r--ydb/library/login/ya.make2
30 files changed, 377 insertions, 1622 deletions
diff --git a/ydb/core/protos/counters_schemeshard.proto b/ydb/core/protos/counters_schemeshard.proto
index 25d3a41d554..8917520bf0d 100644
--- a/ydb/core/protos/counters_schemeshard.proto
+++ b/ydb/core/protos/counters_schemeshard.proto
@@ -763,7 +763,7 @@ enum ETxTypes {
TXTYPE_ADD_SHARDS_SHRED = 98 [(TxTypeOpts) = {Name: "TxAddShardsShred"}];
TXTYPE_CANCEL_SHARDS_SHRED = 99 [(TxTypeOpts) = {Name: "TxCancelShardsShred"}];
- TXTYPE_LOGIN_FINALIZE = 100 [(TxTypeOpts) = {Name: "TxLoginFinalize"}];
+ TXTYPE_DEPRECATED_100 = 100 [(TxTypeOpts) = {Name: "TxDeprecated100"}]; // was TXTYPE_LOGIN_FINALIZE
TXTYPE_PROGRESS_INCREMENTAL_RESTORE = 101 [(TxTypeOpts) = {Name: "TxProgressIncrementalRestore"}];
TXTYPE_INCREMENTAL_RESTORE_SHARD_RESPONSE = 102 [(TxTypeOpts) = {Name: "TxIncrementalRestoreShardResponse"}];
@@ -784,7 +784,7 @@ enum ETxTypes {
TXTYPE_LIST_FORCED_COMPACTION = 114 [(TxTypeOpts) = {Name: "TxListForcedCompaction"}];
TXTYPE_PROGRESS_FORCED_COMPACTION = 115 [(TxTypeOpts) = {Name: "TxProgressForcedCompaction"}];
- TXTYPE_USER_HASHES_MIGRATION = 116 [(TxTypeOpts) = {Name: "TTxUserHashesMigration"}];
+ TXTYPE_DEPRECATED_116 = 116 [(TxTypeOpts) = {Name: "TxDeprecated116"}]; // was TXTYPE_USER_HASHES_MIGRATION
TXTYPE_TABLE_PARTITIONS_STORAGE_FORMAT_SWITCH = 117 [(TxTypeOpts) = {Name: "TxTablePartitionsFormatSwitch"}];
TXTYPE_TABLE_PARTITIONS_STORAGE_FORMAT_SWEEP_STEP = 118 [(TxTypeOpts) = {Name: "TxTablePartitionsFormatSweepStep"}];
diff --git a/ydb/core/security/ldap_auth_provider/ldap_auth_provider_ut.cpp b/ydb/core/security/ldap_auth_provider/ldap_auth_provider_ut.cpp
index 10b72b07061..7efccbf1290 100644
--- a/ydb/core/security/ldap_auth_provider/ldap_auth_provider_ut.cpp
+++ b/ydb/core/security/ldap_auth_provider/ldap_auth_provider_ut.cpp
@@ -58,18 +58,18 @@ private:
ui16 GrpcPort;
};
-NLogin::TLoginProvider::TLoginUserResponse GetLoginResponse(TLdapKikimrServer& server, const TString& login, const TString& password) {
+NLogin::TLoginProvider::TLoginUserResponse GetLoginResponse(TLdapKikimrServer& server, const TString& login) {
TTestActorRuntime* runtime = server.GetRuntime();
NLogin::TLoginProvider provider;
provider.Audience = "/Root";
provider.RotateKeys();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- return provider.LoginUser({.User = login, .Password = password, .ExternalAuth = "ldap"});
+ return provider.LoginUser({.User = login, .ExternalAuth = "ldap"});
}
-TAutoPtr<IEventHandle> LdapAuthenticate(TLdapKikimrServer& server, const TString& login, const TString& password) {
- auto loginResponse = GetLoginResponse(server, login, password);
+TAutoPtr<IEventHandle> LdapAuthenticate(TLdapKikimrServer& server, const TString& login) {
+ auto loginResponse = GetLoginResponse(server, login);
TTestActorRuntime* runtime = server.GetRuntime();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -576,7 +576,8 @@ TCertStorage CertStorage;
void CheckRequiredLdapSettings(std::function<void(NKikimrProto::TLdapAuthentication*, ui16, const TLdapClientOptions&)> initLdapSettings,
const TString& expectedErrorMessage,
- const ESecurityConnectionType& securityConnectionType = ESecurityConnectionType::NON_SECURE) {
+ const ESecurityConnectionType& securityConnectionType = ESecurityConnectionType::NON_SECURE)
+{
TLdapKikimrServer ydbServer(initLdapSettings, {
.CaCertFile = CertStorage.GetCaCertFileName(),
.Type = securityConnectionType
@@ -590,10 +591,9 @@ void CheckRequiredLdapSettings(std::function<void(NKikimrProto::TLdapAuthenticat
}, LdapMock::TLdapMockResponses());
TString login = "ldapuser";
- TString password = "ldapUserPassword";
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Expected return error message");
UNIT_ASSERT_STRINGS_EQUAL(ticketParserResult->Error.Message, expectedErrorMessage);
@@ -601,7 +601,6 @@ void CheckRequiredLdapSettings(std::function<void(NKikimrProto::TLdapAuthenticat
void LdapFetchGroupsWithDefaultGroupAttributeGood(const ESecurityConnectionType& secureType) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings, {
.CaCertFile = CertStorage.GetCaCertFileName(),
@@ -615,7 +614,7 @@ void LdapFetchGroupsWithDefaultGroupAttributeGood(const ESecurityConnectionType&
.UseTls = secureType == ESecurityConnectionType::LDAPS_SCHEME
}, TCorrectLdapResponse::GetResponses(login));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -651,13 +650,12 @@ Y_UNIT_TEST(CanFetchGroupsWithDefaultGroupAttributeNonSecure) {
Y_UNIT_TEST(CanFetchGroupsWithDefaultGroupAttributeDisableNestedGroups) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsDisableSearchNestedGroups);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login, true));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -677,13 +675,12 @@ Y_UNIT_TEST(CanFetchGroupsWithDefaultGroupAttributeDisableNestedGroups) {
Y_UNIT_TEST(CanFetchGroupsFromAdServer) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -703,13 +700,12 @@ Y_UNIT_TEST(CanFetchGroupsFromAdServer) {
Y_UNIT_TEST(CanFetchGroupsWithDisabledRequestToAD) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsDisableSearchNestedGroups);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login, true));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -729,13 +725,12 @@ Y_UNIT_TEST(CanFetchGroupsWithDisabledRequestToAD) {
Y_UNIT_TEST(CanFetchGroupsWithDefaultGroupAttributeUseListOfHosts) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsWithListOfHosts);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -755,13 +750,12 @@ Y_UNIT_TEST(CanFetchGroupsWithDefaultGroupAttributeUseListOfHosts) {
Y_UNIT_TEST(CanFetchGroupsWithCustomGroupAttribute) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsWithCustomGroupAttribute);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login, false, "groupDN"));
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -781,7 +775,6 @@ Y_UNIT_TEST(CanFetchGroupsWithCustomGroupAttribute) {
Y_UNIT_TEST(CanFetchGroupsWithDontExistGroupAttribute) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsWithCustomGroupAttribute);
@@ -814,7 +807,7 @@ Y_UNIT_TEST(CanFetchGroupsWithDontExistGroupAttribute) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -827,7 +820,6 @@ Y_UNIT_TEST(CanFetchGroupsWithDontExistGroupAttribute) {
Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserLogin) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
LdapMock::TLdapMockResponses responses;
responses.BindResponses.push_back({{{.Login = "cn=invalidRobouser,dc=search,dc=yandex,dc=net", .Password = "robouserPassword"}}, {.Status = LdapMock::EStatus::INVALID_CREDENTIALS}});
@@ -836,7 +828,7 @@ Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserLogin) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Expected return error message");
UNIT_ASSERT_STRINGS_EQUAL(ticketParserResult->Error.Message, "Could not login via LDAP");
@@ -845,7 +837,6 @@ Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserLogin) {
Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserPassword) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
LdapMock::TLdapMockResponses responses;
responses.BindResponses.push_back({{{.Login = "cn=robouser,dc=search,dc=yandex,dc=net", .Password = "invalidPassword"}}, {.Status = LdapMock::EStatus::INVALID_CREDENTIALS}});
@@ -854,7 +845,7 @@ Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserPassword) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Expected return error message");
UNIT_ASSERT_STRINGS_EQUAL(ticketParserResult->Error.Message, "Could not login via LDAP");
@@ -863,7 +854,6 @@ Y_UNIT_TEST(CanNotFetchGroupsWithInvalidRobotUserPassword) {
Y_UNIT_TEST(CanNotFetchGroupsWithRemovedUserCredentials) {
TString removedUserLogin = "ldapuser";
- TString removedUserPassword = "ldapUserPassword";
LdapMock::TLdapMockResponses responses;
responses.BindResponses.push_back({{{.Login = "cn=robouser,dc=search,dc=yandex,dc=net", .Password = "robouserPassword"}}, {.Status = LdapMock::EStatus::SUCCESS}});
@@ -888,7 +878,7 @@ Y_UNIT_TEST(CanNotFetchGroupsWithRemovedUserCredentials) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, removedUserLogin, removedUserPassword);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, removedUserLogin);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Expected return error message");
UNIT_ASSERT_STRINGS_EQUAL(ticketParserResult->Error.Message, "Could not login via LDAP");
@@ -896,7 +886,6 @@ Y_UNIT_TEST(CanNotFetchGroupsWithRemovedUserCredentials) {
Y_UNIT_TEST(CanNotFetchGroupsUseInvalidSearchFilter) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
LdapMock::TLdapMockResponses responses;
responses.BindResponses.push_back({{{.Login = "cn=robouser,dc=search,dc=yandex,dc=net", .Password = "robouserPassword"}}, {.Status = LdapMock::EStatus::SUCCESS}});
@@ -905,7 +894,7 @@ Y_UNIT_TEST(CanNotFetchGroupsUseInvalidSearchFilter) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Expected return error message");
UNIT_ASSERT_STRINGS_EQUAL(ticketParserResult->Error.Message, "Could not login via LDAP");
@@ -913,7 +902,6 @@ Y_UNIT_TEST(CanNotFetchGroupsUseInvalidSearchFilter) {
Y_UNIT_TEST(CanRefreshGroupsInfo) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
auto responses = TCorrectLdapResponse::GetResponses(login);
LdapMock::TLdapMockResponses updatedResponses = TCorrectLdapResponse::GetUpdatedResponses(login);
@@ -923,7 +911,7 @@ Y_UNIT_TEST(CanRefreshGroupsInfo) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login));
ldapServer.Start();
- auto loginResponse = GetLoginResponse(ydbServer, login, password);
+ auto loginResponse = GetLoginResponse(ydbServer, login);
TTestActorRuntime* runtime = ydbServer.GetRuntime();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -967,7 +955,6 @@ Y_UNIT_TEST(CanRefreshGroupsInfo) {
Y_UNIT_TEST(CanRefreshGroupsInfoWithDisabledNestedGroups) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
auto responses = TCorrectLdapResponse::GetResponses(login, true);
LdapMock::TLdapMockResponses updatedResponses = TCorrectLdapResponse::GetUpdatedResponses(login, true);
@@ -977,7 +964,7 @@ Y_UNIT_TEST(CanRefreshGroupsInfoWithDisabledNestedGroups) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort(),}, responses);
ldapServer.Start();
- auto loginResponse = GetLoginResponse(ydbServer, login, password);
+ auto loginResponse = GetLoginResponse(ydbServer, login);
TTestActorRuntime* runtime = ydbServer.GetRuntime();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -1021,7 +1008,6 @@ Y_UNIT_TEST(CanRefreshGroupsInfoWithDisabledNestedGroups) {
Y_UNIT_TEST(CanNotRefreshRemovedUser) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings);
auto responses = TCorrectLdapResponse::GetResponses(login);
@@ -1036,7 +1022,7 @@ Y_UNIT_TEST(CanNotRefreshRemovedUser) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- auto loginResponse = GetLoginResponse(ydbServer, login, password);
+ auto loginResponse = GetLoginResponse(ydbServer, login);
TTestActorRuntime* runtime = ydbServer.GetRuntime();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -1072,7 +1058,6 @@ Y_UNIT_TEST(CanNotRefreshRemovedUser) {
Y_UNIT_TEST(CanRefreshGroupsInfoWithError) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings);
auto responses = TCorrectLdapResponse::GetResponses(login);
@@ -1087,7 +1072,7 @@ Y_UNIT_TEST(CanRefreshGroupsInfoWithError) {
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, responses);
ldapServer.Start();
- auto loginResponse = GetLoginResponse(ydbServer, login, password);
+ auto loginResponse = GetLoginResponse(ydbServer, login);
TTestActorRuntime* runtime = ydbServer.GetRuntime();
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -1147,7 +1132,6 @@ Y_UNIT_TEST(CanNotRequestWithEmptyBindPassword) {
Y_UNIT_TEST(CanFetchGroupsWithDelayUpdateSecurityState) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login));
@@ -1159,7 +1143,7 @@ Y_UNIT_TEST(CanFetchGroupsWithDelayUpdateSecurityState) {
provider.RotateKeys();
TActorId sender = runtime->AllocateEdgeActor();
- auto loginResponse = provider.LoginUser({.User = login, .Password = password, .ExternalAuth = "ldap"});
+ auto loginResponse = provider.LoginUser({.User = login, .ExternalAuth = "ldap"});
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
Sleep(TDuration::Seconds(1));
// Send update security state in 1 second after send TEvAuthorizeTicket
@@ -1186,7 +1170,6 @@ Y_UNIT_TEST(CanFetchGroupsWithDelayUpdateSecurityState) {
Y_UNIT_TEST(CanGetErrorIfAppropriateLoginProviderIsAbsent) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettings);
LdapMock::TSimpleServer ldapServer({.Port = ydbServer.GetLdapPort()}, TCorrectLdapResponse::GetResponses(login));
@@ -1198,7 +1181,7 @@ Y_UNIT_TEST(CanGetErrorIfAppropriateLoginProviderIsAbsent) {
provider.RotateKeys();
TActorId sender = runtime->AllocateEdgeActor();
- auto loginResponse = provider.LoginUser({.User = login, .Password = password, .ExternalAuth = "ldap"});
+ auto loginResponse = provider.LoginUser({.User = login, .ExternalAuth = "ldap"});
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
Sleep(TDuration::Seconds(1));
// Do no send update security state
@@ -1215,7 +1198,6 @@ Y_UNIT_TEST(CanGetErrorIfAppropriateLoginProviderIsAbsent) {
Y_UNIT_TEST(CanFetchGroupsWithValidCredentialsUseExternalSaslAuth) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsWithSaslExternalBind, {
.CaCertFile = CertStorage.GetCaCertFileName(),
@@ -1239,7 +1221,7 @@ Y_UNIT_TEST(CanFetchGroupsWithValidCredentialsUseExternalSaslAuth) {
}
}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(!ticketParserResult->HasError(), ticketParserResult->Error);
UNIT_ASSERT(ticketParserResult->Token != nullptr);
@@ -1259,7 +1241,6 @@ Y_UNIT_TEST(CanFetchGroupsWithValidCredentialsUseExternalSaslAuth) {
Y_UNIT_TEST(CanNotFetchGroupsOverSaslExternalWithoutClientCert) {
TString login = "ldapuser";
- TString password = "ldapUserPassword";
TLdapKikimrServer ydbServer(InitLdapSettingsWithSaslExternalBind, {
.CaCertFile = CertStorage.GetCaCertFileName(),
@@ -1281,7 +1262,7 @@ Y_UNIT_TEST(CanNotFetchGroupsOverSaslExternalWithoutClientCert) {
}
}, responses);
ldapServer.Start();
- TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login, password);
+ TAutoPtr<IEventHandle> handle = LdapAuthenticate(ydbServer, login);
TEvTicketParser::TEvAuthorizeTicketResult* ticketParserResult = handle->Get<TEvTicketParser::TEvAuthorizeTicketResult>();
UNIT_ASSERT_C(ticketParserResult->HasError(), "Should be error");
UNIT_ASSERT_EQUAL_C(ticketParserResult->Error.Message, "Could not login via LDAP", ticketParserResult->Error);
diff --git a/ydb/core/security/ticket_parser_ut.cpp b/ydb/core/security/ticket_parser_ut.cpp
index a5ec40b0a82..6ca78ef2a75 100644
--- a/ydb/core/security/ticket_parser_ut.cpp
+++ b/ydb/core/security/ticket_parser_ut.cpp
@@ -37,6 +37,35 @@ using TAccessServiceMock = TTicketParserAccessServiceMock;
using TAccessServiceMockV2 = TTicketParserAccessServiceMockV2;
using TNebiusAccessServiceMock = TTicketParserNebiusAccessServiceMock;
+// Precomputed argon2id + SCRAM-SHA-256 hashes from scram_ut.cpp
+// Password: "password1"
+static const TString PASSWORD1_HASHES = R"({
+ "version": 1,
+ "argon2id": "flbr3YnA9kG67qegwDTaYg==$wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=",
+ "scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
+})";
+
+// The ServerKey of the SCRAM-SHA-256 hash above.
+static const TString PASSWORD1_SCRAM_SERVER_KEY = "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc=";
+
+NLogin::TLoginProvider::TCreateUserRequest MakeCreateUserRequest(const TString& user) {
+ return {
+ .User = user,
+ .HashedPassword = Base64Encode(PASSWORD1_HASHES),
+ };
+}
+
+NLogin::TLoginProvider::TLoginUserRequest MakeLoginUserRequest(const TString& user) {
+ return {
+ .User = user,
+ .HashToValidate = NLogin::TLoginProvider::THashToValidate{
+ .AuthMech = NLoginProto::ESaslAuthMech::Plain,
+ .HashType = NLoginProto::EHashType::ScramSha256,
+ .Hash = PASSWORD1_SCRAM_SERVER_KEY,
+ },
+ };
+}
+
template <class TAccessServiceMock>
void SetUseAccessService(NKikimrProto::TAuthConfig& authConfig);
@@ -176,8 +205,8 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- provider.CreateUser({.User = "user1", .Password = "password1"});
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvAuthorizeTicket(loginResponse.Token)), 0);
@@ -217,12 +246,12 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
provider.CreateGroup({.Group = "group1"});
- provider.CreateUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
provider.AddGroupMembership({.Group = "group1", .Member = "user1"});
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -266,11 +295,11 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
loginProviderDb1.CreateGroup({.Group = "group1"});
- loginProviderDb1.CreateUser({.User = "user1", .Password = "password1"});
+ loginProviderDb1.CreateUser(MakeCreateUserRequest("user1"));
loginProviderDb1.AddGroupMembership({.Group = "group1", .Member = "user1"});
- auto loginResponse = loginProviderDb1.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = loginProviderDb1.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -297,11 +326,11 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
loginProviderDb2.CreateGroup({.Group = "group1"});
- loginProviderDb2.CreateUser({.User = "user1", .Password = "password1"});
+ loginProviderDb2.CreateUser(MakeCreateUserRequest("user1"));
loginProviderDb2.AddGroupMembership({.Group = "group1", .Member = "user1"});
- auto loginResponse = loginProviderDb2.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = loginProviderDb2.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -349,11 +378,11 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
loginProviderDb1.CreateGroup({.Group = "group1"});
- loginProviderDb1.CreateUser({.User = "user1", .Password = "password1"});
+ loginProviderDb1.CreateUser(MakeCreateUserRequest("user1"));
loginProviderDb1.AddGroupMembership({.Group = "group1", .Member = "user1"});
- auto loginResponse = loginProviderDb1.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = loginProviderDb1.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -438,12 +467,12 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
provider.CreateGroup({.Group = "group1"});
- provider.CreateUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
provider.AddGroupMembership({.Group = "group1", .Member = "user1"});
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -524,7 +553,7 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
provider.CreateGroup({.Group = "group1"});
- provider.CreateUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
provider.AddGroupMembership({.Group = "group1", .Member = "user1"});
NLogin::TLoginProvider emptyProvider;
@@ -532,7 +561,7 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(emptyProvider.GetSecurityState())), 0);
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -590,12 +619,12 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
provider.CreateGroup({.Group = "group1"});
- provider.CreateUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
provider.AddGroupMembership({.Group = "group1", .Member = "user1"});
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "");
@@ -652,8 +681,8 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) {
TActorId sender = runtime->AllocateEdgeActor();
runtime->Send(new IEventHandle(MakeTicketParserID(), sender, new TEvTicketParser::TEvUpdateLoginSecurityState(provider.GetSecurityState())), 0);
- provider.CreateUser({.User = "user1", .Password = "password1"});
- auto loginResponse = provider.LoginUser({.User = "user1", .Password = "password1"});
+ provider.CreateUser(MakeCreateUserRequest("user1"));
+ auto loginResponse = provider.LoginUser(MakeLoginUserRequest("user1"));
TString emptyUserToken = "";
diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp
index b160e5599e8..3a950a672c2 100644
--- a/ydb/core/tx/schemeshard/schemeshard__init.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp
@@ -1406,13 +1406,6 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
}
{
- ui64 isOldArgonHashFormatMigrationCompletedVal = 0;
- RETURN_IF_NO_PRECHARGED(Self->ReadSysValue(db, Schema::SysParam_IsOldArgonHashFormatMigrationCompleted,
- isOldArgonHashFormatMigrationCompletedVal));
- Self->IsOldArgonHashFormatMigrationCompleted = isOldArgonHashFormatMigrationCompletedVal;
- }
-
- {
ui64 sweepStatusVal = 0;
RETURN_IF_NO_PRECHARGED(Self->ReadSysValue(db, Schema::SysParam_TablePartitionsFormatSweepStatus, sweepStatusVal));
switch (sweepStatusVal) {
diff --git a/ydb/core/tx/schemeshard/schemeshard__login.cpp b/ydb/core/tx/schemeshard/schemeshard__login.cpp
index 662ccf0c20b..a0e27c51bfe 100644
--- a/ydb/core/tx/schemeshard/schemeshard__login.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__login.cpp
@@ -11,11 +11,9 @@ namespace NSchemeShard {
struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
TEvSchemeShard::TEvLogin::TPtr Request;
- NLogin::TLoginProvider::TLoginUserResponse Response;
TPathId SubDomainPathId;
bool NeedPublishOnComplete = false;
- bool SendFinalizeEvent = false;
- TString ErrMessage;
+ THolder<TEvSchemeShard::TEvLoginResult> Result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
TTxLogin(TSelf *self, TEvSchemeShard::TEvLogin::TPtr &ev)
: TRwTxBase(self)
@@ -64,33 +62,19 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
const auto& loginRequest = GetLoginRequest();
if (!loginRequest.ExternalAuth.has_value()) {
if (!AppData(ctx)->AuthConfig.GetEnableLoginAuthentication()) {
- ErrMessage = "Login authentication is disabled";
- } else {
- CheckLockOutUserAndSetErrorIfAny(loginRequest.User, db);
+ Result->Record.SetError("Login authentication is disabled");
+ return;
+ }
+ if (CheckLockOutUserAndSetErrorIfAny(loginRequest.User, db)) {
+ return;
}
}
- if (ErrMessage) {
- SendError();
- return;
- }
-
- TString hashValues;
- if (Self->LoginProvider.NeedVerifyHash(loginRequest, &Response, &hashValues)) {
- if (loginRequest.HashToValidate.has_value()) {
- Self->LoginProvider.VerifyHashValues(loginRequest, &Response, hashValues);
- SendFinalizeEvent = true;
- } else if (loginRequest.Password.has_value()) { // for backward compatibility
- ctx.Send(
- Self->LoginHelper,
- MakeHolder<TEvPrivate::TEvVerifyPassword>(loginRequest, Response, Request->Sender, hashValues),
- 0,
- Request->Cookie
- );
- }
- } else {
- SendFinalizeEvent = true;
+ const auto response = Self->LoginProvider.LoginUser(loginRequest);
+ if (!loginRequest.ExternalAuth.has_value()) {
+ UpdateLoginSidsStats(response, db);
}
+ FillResult(response);
}
void DoComplete(const TActorContext &ctx) override {
@@ -98,23 +82,22 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
Self->PublishToSchemeBoard(TTxId(), {SubDomainPathId}, ctx);
}
- if (SendFinalizeEvent) {
- auto event = MakeHolder<TEvPrivate::TEvLoginFinalize>(
- GetLoginRequest(), Response, Request->Sender, "", /*needUpdateCache*/ false
- );
- TEvPrivate::TEvLoginFinalize::TPtr eventPtr = (TEventHandle<TEvPrivate::TEvLoginFinalize>*) new IEventHandle(
- Self->SelfId(), Self->SelfId(), event.Release()
- );
- Self->Execute(Self->CreateTxLoginFinalize(eventPtr), ctx);
- }
-
+ const TString& error = Result->Record.GetError();
LOG_DEBUG_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
"TTxLogin Complete"
- << ", with " << (ErrMessage ? "error: " + ErrMessage : "no errors")
+ << ", with " << (error ? "error: " + error : "no errors")
<< ", at schemeshard: " << Self->TabletID());
-}
+
+ Self->Send(Request->Sender, std::move(Result), 0, Request->Cookie);
+ }
private:
+ bool IsAdmin() const {
+ const auto& user = Request->Get()->Record.GetUser();
+ const auto userToken = NKikimr::BuildLocalUserToken(Self->LoginProvider, user);
+ return IsAdministrator(AppData(), &userToken);
+ }
+
void RotateKeys(const TActorContext& ctx, NIceDb::TNiceDb& db) {
LOG_DEBUG_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "TTxLogin RotateKeys at schemeshard: " << Self->TabletID());
std::vector<ui64> keysExpired;
@@ -141,14 +124,15 @@ private:
}
}
- void CheckLockOutUserAndSetErrorIfAny(const TString& user, NIceDb::TNiceDb& db) {
+ // Returns true if the user is locked out and an error has been set into the result.
+ bool CheckLockOutUserAndSetErrorIfAny(const TString& user, NIceDb::TNiceDb& db) {
using namespace NLogin;
const TLoginProvider::TCheckLockOutResponse checkLockOutResponse = Self->LoginProvider.CheckLockOutUser({.User = user});
switch (checkLockOutResponse.Status) {
case TLoginProvider::TCheckLockOutResponse::EStatus::SUCCESS:
case TLoginProvider::TCheckLockOutResponse::EStatus::INVALID_USER: {
- ErrMessage = checkLockOutResponse.Error;
- return;
+ Result->Record.SetError(checkLockOutResponse.Error);
+ return true;
}
case TLoginProvider::TCheckLockOutResponse::EStatus::RESET: {
const auto& sid = Self->LoginProvider.Sids[user];
@@ -160,17 +144,55 @@ private:
break;
}
}
+ return false;
}
- void SendError() {
- THolder<TEvSchemeShard::TEvLoginResult> result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
- result->Record.SetError(ErrMessage);
- Self->Send(
- Request->Sender,
- std::move(result),
- 0,
- Request->Cookie
- );
+ void FillResult(const NLogin::TLoginProvider::TLoginUserResponse& response) {
+ switch (response.Status) {
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
+ if (response.ServerSignature.has_value()) {
+ Result->Record.SetServerSignature(*response.ServerSignature);
+ }
+ Result->Record.SetToken(response.Token);
+ Result->Record.SetSanitizedToken(response.SanitizedToken);
+ Result->Record.SetIsAdmin(IsAdmin());
+ break;
+ }
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD:
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_HASH_TYPE:
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSUPPORTED_SASL_MECHANISM:
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
+ Result->Record.SetError(response.Error);
+ break;
+ }
+ }
+ }
+
+ void UpdateLoginSidsStats(const NLogin::TLoginProvider::TLoginUserResponse& response, NIceDb::TNiceDb& db) {
+ const TString& user = Request->Get()->Record.GetUser();
+ switch (response.Status) {
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
+ const auto& sid = Self->LoginProvider.Sids[user];
+ db.Table<Schema::LoginSids>()
+ .Key(user)
+ .Update<Schema::LoginSids::LastSuccessfulAttempt, Schema::LoginSids::FailedAttemptCount>(
+ ToMicroSeconds(sid.LastSuccessfulLogin), sid.FailedLoginAttemptCount
+ );
+ break;
+ }
+ case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD: {
+ const auto& sid = Self->LoginProvider.Sids[user];
+ db.Table<Schema::LoginSids>()
+ .Key(user)
+ .Update<Schema::LoginSids::LastFailedAttempt, Schema::LoginSids::FailedAttemptCount>(
+ ToMicroSeconds(sid.LastFailedLogin), sid.FailedLoginAttemptCount
+ );
+ }
+ default:
+ break;
+ }
}
};
diff --git a/ydb/core/tx/schemeshard/schemeshard__login_finalize.cpp b/ydb/core/tx/schemeshard/schemeshard__login_finalize.cpp
deleted file mode 100644
index 015f7278ea8..00000000000
--- a/ydb/core/tx/schemeshard/schemeshard__login_finalize.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "schemeshard_impl.h"
-#include <ydb/library/security/util.h>
-#include <ydb/core/protos/auth.pb.h>
-#include <ydb/core/base/auth.h>
-#include <ydb/core/base/local_user_token.h>
-
-namespace NKikimr {
-namespace NSchemeShard {
-
-struct TSchemeShard::TTxLoginFinalize : TSchemeShard::TRwTxBase {
-private:
- TEvPrivate::TEvLoginFinalize::TPtr LoginFinalizeEventPtr;
- TString ErrMessage;
-
-public:
- TTxLoginFinalize(TSelf *self, TEvPrivate::TEvLoginFinalize::TPtr &ev)
- : TRwTxBase(self)
- , LoginFinalizeEventPtr(std::move(ev))
- {}
-
- TTxType GetTxType() const override {
- return TXTYPE_LOGIN_FINALIZE;
- }
-
- void DoExecute(TTransactionContext& txc, const TActorContext& ctx) override {
- LOG_DEBUG_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
- "TTxLoginFinalize Execute"
- << " at schemeshard: " << Self->TabletID());
-
- const auto& event = *LoginFinalizeEventPtr->Get();
- if (event.NeedUpdateCache) {
- const auto isSuccessVerifying =
- event.CheckResult.Status == NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS;
- Self->LoginProvider.UpdateCache(
- event.Request,
- event.PasswordHash,
- isSuccessVerifying
- );
- }
- const auto response = Self->LoginProvider.LoginUser(event.Request, event.CheckResult);
-
- if (!LoginFinalizeEventPtr->Get()->Request.ExternalAuth.has_value()) {
- UpdateLoginSidsStats(response, txc);
- }
- if (!response.Error.empty()) {
- ErrMessage = response.Error;
- SendError(response.Error);
- return;
- }
- FillResult(response);
- }
-
- void DoComplete(const TActorContext &ctx) override {
- LOG_DEBUG_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
- "TTxLoginFinalize Completed"
- << ", with " << (ErrMessage ? "error: " + ErrMessage : "no errors")
- << " at schemeshard: " << Self->TabletID());
- }
-
-private:
- bool IsAdmin(const TString& user) const {
- const auto userToken = NKikimr::BuildLocalUserToken(Self->LoginProvider, user);
- return IsAdministrator(AppData(), &userToken);
- }
-
- void FillResult(const NLogin::TLoginProvider::TLoginUserResponse& response) {
- THolder<TEvSchemeShard::TEvLoginResult> result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
- switch (response.Status) {
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
- if (response.ServerSignature.has_value()) {
- result->Record.SetServerSignature(*response.ServerSignature);
- }
-
- result->Record.SetToken(response.Token);
- result->Record.SetSanitizedToken(response.SanitizedToken);
- result->Record.SetIsAdmin(IsAdmin(LoginFinalizeEventPtr->Get()->Request.User));
- break;
- }
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD:
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_HASH_TYPE:
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSUPPORTED_SASL_MECHANISM:
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
- result->Record.SetError(response.Error);
- break;
- }
- }
- Self->Send(
- LoginFinalizeEventPtr->Get()->Source,
- std::move(result),
- 0,
- LoginFinalizeEventPtr->Cookie
- );
- }
-
- void SendError(const TString& error) {
- auto result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
- result->Record.SetError(error);
- Self->Send(
- LoginFinalizeEventPtr->Get()->Source,
- std::move(result),
- 0,
- LoginFinalizeEventPtr->Cookie
- );
- }
-
- void UpdateLoginSidsStats(const NLogin::TLoginProvider::TLoginUserResponse& response, TTransactionContext& txc) {
- NIceDb::TNiceDb db(txc.DB);
- switch (response.Status) {
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::SUCCESS: {
- const auto& sid = Self->LoginProvider.Sids[LoginFinalizeEventPtr->Get()->Request.User];
- db.Table<Schema::LoginSids>()
- .Key(LoginFinalizeEventPtr->Get()->Request.User)
- .Update<Schema::LoginSids::LastSuccessfulAttempt, Schema::LoginSids::FailedAttemptCount>(
- ToMicroSeconds(sid.LastSuccessfulLogin), sid.FailedLoginAttemptCount
- );
- break;
- }
- case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD: {
- const auto& sid = Self->LoginProvider.Sids[LoginFinalizeEventPtr->Get()->Request.User];
- db.Table<Schema::LoginSids>()
- .Key(LoginFinalizeEventPtr->Get()->Request.User)
- .Update<Schema::LoginSids::LastFailedAttempt, Schema::LoginSids::FailedAttemptCount>(
- ToMicroSeconds(sid.LastFailedLogin), sid.FailedLoginAttemptCount
- );
- }
- default:
- break;
- }
- }
-};
-
-NTabletFlatExecutor::ITransaction* TSchemeShard::CreateTxLoginFinalize(TEvPrivate::TEvLoginFinalize::TPtr &ev) {
- return new TTxLoginFinalize(this, ev);
-}
-
-}}
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
index 5cac29745f8..cee51ab22f5 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
@@ -99,10 +99,11 @@ public:
} else {
auto& sid = context.SS->LoginProvider.Sids[modifyUser.GetUser()];
db.Table<Schema::LoginSids>().Key(sid.Name).Update<Schema::LoginSids::SidType,
+ Schema::LoginSids::SidHash, // explicitly erase deprecated field
Schema::LoginSids::PasswordHashes,
Schema::LoginSids::IsEnabled,
Schema::LoginSids::FailedAttemptCount>(
- sid.Type, sid.PasswordHashes, sid.IsEnabled, sid.FailedLoginAttemptCount);
+ sid.Type, "", sid.PasswordHashes, sid.IsEnabled, sid.FailedLoginAttemptCount);
result->SetStatus(NKikimrScheme::StatusSuccess);
AddIsUserAdmin(modifyUser.GetUser(), context.SS->LoginProvider, additionalParts);
diff --git a/ydb/core/tx/schemeshard/schemeshard__user_hashes_migration.cpp b/ydb/core/tx/schemeshard/schemeshard__user_hashes_migration.cpp
deleted file mode 100644
index dd73d7486bb..00000000000
--- a/ydb/core/tx/schemeshard/schemeshard__user_hashes_migration.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-#include "schemeshard_impl.h"
-
-#include <ydb/library/login/hashes_checker/hashes_checker.h>
-#include <ydb/library/login/password_checker/password_checker.h>
-#include <ydb/library/login/protos/login.pb.h>
-
-#include <util/generic/vector.h>
-#include <util/random/random.h>
-#include <algorithm>
-
-
-namespace NKikimr {
-namespace NSchemeShard {
-
-using namespace NTabletFlatExecutor;
-
-namespace {
-
-TString GenerateRandomPassword(const NLogin::TPasswordComplexity& complexity) {
- static constexpr char lowerLetters[] = "abcdefghijklmnopqrstuvwxyz";
- static constexpr char upperLetters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- static constexpr char digits[] = "0123456789";
- static constexpr size_t lowerCount = sizeof(lowerLetters) - 1;
- static constexpr size_t upperCount = sizeof(upperLetters) - 1;
- static constexpr size_t digitsCount = sizeof(digits) - 1;
-
-
- TVector<char> specialChars(complexity.SpecialChars.begin(), complexity.SpecialChars.end());
-
- TVector<char> password;
-
- // Add required minimum counts for each character class
- for (size_t i = 0; i < complexity.MinLowerCaseCount; ++i) {
- password.push_back(lowerLetters[RandomNumber<size_t>(lowerCount)]);
- }
- for (size_t i = 0; i < complexity.MinUpperCaseCount; ++i) {
- password.push_back(upperLetters[RandomNumber<size_t>(upperCount)]);
- }
- for (size_t i = 0; i < complexity.MinNumbersCount; ++i) {
- password.push_back(digits[RandomNumber<size_t>(digitsCount)]);
- }
- for (size_t i = 0; i < complexity.MinSpecialCharsCount; ++i) {
- password.push_back(specialChars[RandomNumber<size_t>(specialChars.size())]);
- }
-
- size_t minLength = std::max(complexity.MinLength, static_cast<size_t>(8));
- // Fill remaining positions with random chars from all allowed categories
- if (password.size() < minLength) {
-
- TVector<char> pool;
- pool.insert(pool.end(), lowerLetters, lowerLetters + lowerCount);
- pool.insert(pool.end(), upperLetters, upperLetters + upperCount);
- pool.insert(pool.end(), digits, digits + digitsCount);
- pool.insert(pool.end(), specialChars.begin(), specialChars.end());
-
- while (password.size() < minLength) {
- password.push_back(pool[RandomNumber<size_t>(pool.size())]);
- }
- }
-
-
- // Shuffle to avoid predictable prefix pattern
- for (size_t i = password.size() - 1; i > 0; --i) {
- size_t j = RandomNumber<size_t>(i + 1);
- std::swap(password[i], password[j]);
- }
-
- return TString(password.begin(), password.end());
-}
-
-} // anonymous namespace
-
-struct TSchemeShard::TTxUserHashesMigration : public TTransactionBase<TSchemeShard> {
- bool IsLoginProviderModified = false;
-
- TTxUserHashesMigration(TSelf* self)
- : TTransactionBase<TSchemeShard>(self)
- {}
-
- TTxType GetTxType() const override {
- return TXTYPE_USER_HASHES_MIGRATION;
- }
-
- bool Execute(TTransactionContext &txc, const TActorContext &ctx) override {
- LOG_DEBUG_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
- "TTxUserHashesMigration Execute at schemeshard: " << Self->TabletID());
-
- NIceDb::TNiceDb db(txc.DB);
- for (const auto& [sidName, sid] : Self->LoginProvider.Sids) {
- if (sid.Type == NLoginProto::ESidType::USER) {
- if (!sid.PasswordHashes) { // change password for user with unsupported password hash format
- auto response = Self->LoginProvider.ModifyUser({
- .User = sid.Name,
- .Password = GenerateRandomPassword(Self->LoginProvider.GetPasswordCheckParameters()),
- });
-
- if (response.Error) {
- LOG_ERROR_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "TTxUserHashesMigration Execute"
- << ", can't set generated password in place unacceptable argon hash: "
- << response.Error << ", at schemeshard: "<< Self->TabletID());
- continue;
- }
-
- IsLoginProviderModified = true;
- }
-
- db.Table<Schema::LoginSids>().Key(sidName).Update<Schema::LoginSids::PasswordHashes>(sid.PasswordHashes);
- }
- }
-
- Self->IsOldArgonHashFormatMigrationCompleted = true;
- db.Table<Schema::SysParams>().Key(Schema::SysParam_IsOldArgonHashFormatMigrationCompleted).Update(
- NIceDb::TUpdate<Schema::SysParams::Value>("1"));
-
- if (IsLoginProviderModified) {
- TPathId subDomainPathId = Self->GetCurrentSubDomainPathId();
- TSubDomainInfo::TPtr domainPtr = Self->ResolveDomainInfo(subDomainPathId);
- domainPtr->UpdateSecurityState(Self->LoginProvider.GetSecurityState());
- domainPtr->IncSecurityStateVersion();
- Self->PersistSubDomainSecurityStateVersion(db, subDomainPathId, *domainPtr);
- }
-
- return true;
- }
-
- void Complete(const TActorContext &ctx) override {
- LOG_INFO_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
- "TTxUserHashesMigration Complete, at schemeshard: "<< Self->TabletID());
-
- if (IsLoginProviderModified) {
- Self->PublishToSchemeBoard(TTxId(), {Self->GetCurrentSubDomainPathId()}, ctx);
- }
- }
-};
-
-ITransaction* TSchemeShard::CreateTxUserHashesMigration() {
- return new TTxUserHashesMigration(this);
-}
-
-} // NSchemeShard
-} // NKikimr
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
index ce875b396d0..a7a62858333 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
@@ -1,6 +1,5 @@
#include "schemeshard_impl.h"
#include "schemeshard__local_index_migration.h"
-#include "schemeshard_login_helper.h"
#include "schemeshard_svp_migration.h"
#include "olap/bg_tasks/adapter/adapter.h"
@@ -378,10 +377,6 @@ void TSchemeShard::ActivateAfterInitialization(const TActorContext& ctx, TActiva
InitializeTabletMigrations();
}
- if (!IsOldArgonHashFormatMigrationCompleted) {
- Execute(CreateTxUserHashesMigration(), ctx);
- }
-
ResumeExports(opts.ExportIds, ctx);
ResumeImports(opts.ImportsIds, ctx);
ResumeCdcStreamScans(opts.CdcStreamScans, ctx);
@@ -5569,8 +5564,7 @@ TSchemeShard::TSchemeShard(const TActorId &tablet, TTabletStorageInfo *info)
}), {
.AttemptThreshold = AppData()->AuthConfig.GetAccountLockout().GetAttemptThreshold(),
.AttemptResetDuration = AppData()->AuthConfig.GetAccountLockout().GetAttemptResetDuration()
- },
- IsLoginCacheEnabled, {})
+ })
{
TabletCountersPtr.Reset(new TProtobufTabletCounters<
ESimpleCounters_descriptor,
@@ -5609,9 +5603,6 @@ NTabletPipe::TClientConfig TSchemeShard::GetPipeClientConfig() {
return config;
}
-bool TSchemeShard::IsLoginCacheEnabled() {
- return AppData()->FeatureFlags.GetEnableLoginCache();
-}
void TSchemeShard::FillTableSchemaVersion(ui64 tableSchemaVersion, NKikimrSchemeOp::TTableDescription* tableDescr) const {
tableDescr->SetTableSchemaVersion(tableSchemaVersion);
@@ -5631,7 +5622,6 @@ void TSchemeShard::Die(const TActorContext &ctx) {
ctx.Send(SchemeBoardPopulator, new TEvents::TEvPoisonPill());
ctx.Send(TxAllocatorClient, new TEvents::TEvPoisonPill());
ctx.Send(SysPartitionStatsCollector, new TEvents::TEvPoisonPill());
- ctx.Send(LoginHelper, new TEvents::TEvPoisonPill());
if (TabletMigrator) {
ctx.Send(TabletMigrator, new TEvents::TEvPoisonPill());
@@ -5775,8 +5765,6 @@ void TSchemeShard::OnActivateExecutor(const TActorContext &ctx) {
Execute(CreateTxInitSchema(), ctx);
SubscribeConsoleConfigs(ctx);
-
- LoginHelper = Register(CreateLoginHelper(this->LoginProvider).Release());
}
// This is overriden as noop in order to activate the table only at the end of Init transaction
@@ -6087,7 +6075,6 @@ void TSchemeShard::StateWork(STFUNC_SIG) {
HFuncTraced(TEvPrivate::TEvPersistTopicStats, Handle);
HFuncTraced(TEvSchemeShard::TEvLogin, Handle);
- HFuncTraced(TEvPrivate::TEvLoginFinalize, Handle);
HFuncTraced(TEvSchemeShard::TEvListUsers, Handle);
HFuncTraced(TEvDataShard::TEvProposeTransactionAttachResult, Handle);
@@ -9164,10 +9151,6 @@ void TSchemeShard::Handle(TEvSchemeShard::TEvLogin::TPtr &ev, const TActorContex
Execute(CreateTxLogin(ev), ctx);
}
-void TSchemeShard::Handle(TEvPrivate::TEvLoginFinalize::TPtr &ev, const TActorContext &ctx) {
- Execute(CreateTxLoginFinalize(ev), ctx);
-}
-
void TSchemeShard::Handle(TEvSchemeShard::TEvListUsers::TPtr &ev, const TActorContext &ctx) {
Execute(CreateTxListUsers(ev), ctx);
}
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h
index 5a45ff03727..9785f93097a 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.h
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.h
@@ -13,7 +13,6 @@
#include "schemeshard_forced_compaction.h"
#include "schemeshard_import.h"
#include "schemeshard_info_types.h"
-#include "schemeshard_login_helper.h"
#include "schemeshard_path.h"
#include "schemeshard_path_element.h"
#include "schemeshard_private.h"
@@ -427,8 +426,6 @@ public:
bool EnableExternalSourceSchemaInference = false;
bool EnableMoveColumnTable = false;
- bool IsOldArgonHashFormatMigrationCompleted = false;
-
TShardDeleter ShardDeleter;
// Counter-strike stuff
@@ -1116,9 +1113,6 @@ public:
struct TTxCleanDroppedPaths;
NTabletFlatExecutor::ITransaction* CreateTxCleanDroppedPaths();
- struct TTxUserHashesMigration;
- NTabletFlatExecutor::ITransaction* CreateTxUserHashesMigration();
-
void ScheduleCleanDroppedPaths();
void Handle(TEvPrivate::TEvCleanDroppedPaths::TPtr& ev, const TActorContext& ctx);
@@ -1265,8 +1259,6 @@ public:
struct TTxLogin;
NTabletFlatExecutor::ITransaction* CreateTxLogin(TEvSchemeShard::TEvLogin::TPtr &ev);
- struct TTxLoginFinalize;
- NTabletFlatExecutor::ITransaction* CreateTxLoginFinalize(TEvPrivate::TEvLoginFinalize::TPtr &ev);
struct TTxListUsers;
NTabletFlatExecutor::ITransaction* CreateTxListUsers(TEvSchemeShard::TEvListUsers::TPtr &ev);
@@ -1585,7 +1577,6 @@ public:
void Handle(NConsole::TEvConsole::TEvConfigNotificationRequest::TPtr &ev, const TActorContext &ctx);
void Handle(TEvSchemeShard::TEvLogin::TPtr& ev, const TActorContext& ctx);
- void Handle(TEvPrivate::TEvLoginFinalize::TPtr& ev, const TActorContext& ctx);
void Handle(TEvSchemeShard::TEvListUsers::TPtr& ev, const TActorContext& ctx);
void Handle(TEvPrivate::TEvProgressTablePartitionsFormatSweep::TPtr& ev, const TActorContext& ctx);
@@ -2211,7 +2202,6 @@ public:
void SetShardsQuota(ui64 value) override;
NLogin::TLoginProvider LoginProvider;
- TActorId LoginHelper;
THolder<TRootShredManager> RootShredManager = nullptr;
THolder<TTenantShredManager> TenantShredManager = nullptr;
@@ -2236,8 +2226,6 @@ private:
NKikimrSubDomains::TProcessingParams CreateRootProcessingParams(const TActorContext &ctx);
static NTabletPipe::TClientConfig GetPipeClientConfig();
- static bool IsLoginCacheEnabled();
-
public:
static const NKikimrConfig::TDomainsConfig& GetDomainsConfig();
diff --git a/ydb/core/tx/schemeshard/schemeshard_login_helper.cpp b/ydb/core/tx/schemeshard/schemeshard_login_helper.cpp
deleted file mode 100644
index ea408f159c9..00000000000
--- a/ydb/core/tx/schemeshard/schemeshard_login_helper.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "schemeshard_login_helper.h"
-#include "schemeshard_private.h"
-#include <ydb/library/actors/core/actor_bootstrapped.h>
-#include <ydb/library/actors/core/events.h>
-#include <ydb/library/actors/core/hfunc.h>
-#include <ydb/library/login/login.h>
-
-namespace NKikimr::NSchemeShard {
-
-class TLoginHelper : public NActors::TActorBootstrapped<TLoginHelper> {
-public:
- explicit TLoginHelper(const NLogin::TLoginProvider& loginProvider)
- : LoginProvider_(loginProvider)
- {}
-
- void Bootstrap() {
- Become(&TThis::StateWork);
- }
-
- STATEFN(StateWork) {
- switch (ev->GetTypeRewrite()) {
- hFunc(TEvPrivate::TEvVerifyPassword, VerifyPassword);
- cFunc(NActors::TEvents::TEvPoison::EventType, PassAway);
- }
- }
-
-private:
- void VerifyPassword(TEvPrivate::TEvVerifyPassword::TPtr& ev) {
- const bool isSuccessVerifying = LoginProvider_.VerifyArgonHash(ev->Get()->Request, ev->Get()->PasswordHash);
- if (!isSuccessVerifying) {
- ev->Get()->CheckResult.Status = NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD;
- ev->Get()->CheckResult.Error = "Invalid password";
- }
- Send(
- ev->Sender,
- MakeHolder<TEvPrivate::TEvLoginFinalize>(
- ev->Get()->Request,
- ev->Get()->CheckResult,
- ev->Get()->Source,
- ev->Get()->PasswordHash,
- /*needUpdateCache*/ true
- ),
- 0,
- ev->Cookie
- );
- }
-
-private:
- const NLogin::TLoginProvider& LoginProvider_;
-};
-
-THolder<NActors::IActor> CreateLoginHelper(const NLogin::TLoginProvider& loginProvider) {
- return MakeHolder<TLoginHelper>(loginProvider);
-}
-
-} // namespace NKikimr::NSchemeShard
diff --git a/ydb/core/tx/schemeshard/schemeshard_login_helper.h b/ydb/core/tx/schemeshard/schemeshard_login_helper.h
deleted file mode 100644
index d17666bff73..00000000000
--- a/ydb/core/tx/schemeshard/schemeshard_login_helper.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include <ydb/library/actors/core/actor.h>
-
-namespace NLogin {
- class TLoginProvider;
-}
-
-namespace NKikimr::NSchemeShard {
-
-THolder<NActors::IActor> CreateLoginHelper(const NLogin::TLoginProvider& loginProvider);
-
-} // namespace NKikimr::NSchemeShard
diff --git a/ydb/core/tx/schemeshard/schemeshard_private.h b/ydb/core/tx/schemeshard/schemeshard_private.h
index ddb7bf9d61a..6478fd45c39 100644
--- a/ydb/core/tx/schemeshard/schemeshard_private.h
+++ b/ydb/core/tx/schemeshard/schemeshard_private.h
@@ -8,7 +8,6 @@
#include <ydb/library/actors/core/event_local.h>
#include <ydb/library/actors/core/events.h>
-#include <ydb/library/login/login.h>
#include <util/datetime/base.h>
@@ -49,8 +48,6 @@ namespace TEvPrivate {
EvRunShred,
EvRunTenantShred,
EvAddNewShardToShred,
- EvVerifyPassword,
- EvLoginFinalize,
EvContinuousBackupCleanerResult,
EvTestNotifySubdomainCleanup,
EvFlushConditionalEraseBatch,
@@ -327,51 +324,6 @@ namespace TEvPrivate {
{}
};
- struct TEvVerifyPassword : public NActors::TEventLocal<TEvVerifyPassword, EvVerifyPassword> {
- public:
- TEvVerifyPassword(
- const NLogin::TLoginProvider::TLoginUserRequest& request,
- const NLogin::TLoginProvider::TPasswordCheckResult& checkResult,
- const NActors::TActorId source,
- const TString& passwordHash
- )
- : Request(request)
- , CheckResult(checkResult)
- , Source(source)
- , PasswordHash(passwordHash)
- {}
-
- public:
- const NLogin::TLoginProvider::TLoginUserRequest Request;
- NLogin::TLoginProvider::TPasswordCheckResult CheckResult;
- const NActors::TActorId Source; // actorId of the initial schemeshard client which requested user login
- const TString PasswordHash;
- };
-
- struct TEvLoginFinalize : public NActors::TEventLocal<TEvLoginFinalize, EvLoginFinalize> {
- public:
- TEvLoginFinalize(
- const NLogin::TLoginProvider::TLoginUserRequest& request,
- const NLogin::TLoginProvider::TPasswordCheckResult& checkResult,
- const NActors::TActorId source,
- const TString& passwordHash,
- const bool needUpdateCache
- )
- : Request(request)
- , CheckResult(checkResult)
- , Source(source)
- , PasswordHash(passwordHash)
- , NeedUpdateCache(needUpdateCache)
- {}
-
- public:
- const NLogin::TLoginProvider::TLoginUserRequest Request;
- const NLogin::TLoginProvider::TPasswordCheckResult CheckResult;
- const NActors::TActorId Source; // actorId of the initial schemeshard client which requested user login
- const TString PasswordHash;
- const bool NeedUpdateCache;
- };
-
struct TEvContinuousBackupCleanerResult : public NActors::TEventLocal<TEvContinuousBackupCleanerResult, EvContinuousBackupCleanerResult> {
public:
TEvContinuousBackupCleanerResult(ui64 backupId, TPathId item, bool success, const TString& error = "")
diff --git a/ydb/core/tx/schemeshard/schemeshard_schema.h b/ydb/core/tx/schemeshard/schemeshard_schema.h
index 76c033ea986..40652564916 100644
--- a/ydb/core/tx/schemeshard/schemeshard_schema.h
+++ b/ydb/core/tx/schemeshard/schemeshard_schema.h
@@ -2838,7 +2838,7 @@ struct Schema : NIceDb::Schema {
static constexpr ui64 SysParam_TenantInitState = 9;
static constexpr ui64 SysParam_ServerlessStorageLastBillTime = 10;
static constexpr ui64 SysParam_MaxIncompatibleChange = 11;
- static constexpr ui64 SysParam_IsOldArgonHashFormatMigrationCompleted = 12;
+ // static constexpr ui64 SysParam_IsOldArgonHashFormatMigrationCompleted = 12; deprecated
static constexpr ui64 SysParam_TablePartitionsFormatSweepStatus = 13;
static constexpr ui64 SysParam_TablePartitionsFormatSweepTarget = 14;
diff --git a/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp b/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp
index 46df8807e3f..9dc5438b889 100644
--- a/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp
+++ b/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp
@@ -2715,23 +2715,6 @@ namespace NSchemeShardUT_Private {
return event->Record;
}
- NKikimrScheme::TEvLoginResult LoginFinalize(
- TTestActorRuntime& runtime,
- const NLogin::TLoginProvider::TLoginUserRequest& request,
- const NLogin::TLoginProvider::TPasswordCheckResult& checkResult,
- const TString& passwordHash,
- const bool needUpdateCache
- ) {
- const auto evLoginFinalize = new NSchemeShard::TEvPrivate::TEvLoginFinalize(
- request, checkResult, runtime.AllocateEdgeActor(), passwordHash, needUpdateCache
- );
- AsyncSend(runtime, TTestTxConfig::SchemeShard, evLoginFinalize);
- TAutoPtr<IEventHandle> handle;
- const auto event = runtime.GrabEdgeEvent<TEvSchemeShard::TEvLoginResult>(handle);
- UNIT_ASSERT(event);
- return event->Record;
- }
-
void ModifyUser(TTestActorRuntime& runtime, ui64 txId, const TString& database, std::function<void(::NKikimrSchemeOp::TLoginModifyUser*)>&& initiator) {
auto modifyTx = std::make_unique<TEvSchemeShard::TEvModifySchemeTransaction>(txId, TTestTxConfig::SchemeShard);
auto transaction = modifyTx->Record.AddTransaction();
diff --git a/ydb/core/tx/schemeshard/ut_helpers/helpers.h b/ydb/core/tx/schemeshard/ut_helpers/helpers.h
index 553d8d4a596..becb5f7d0ca 100644
--- a/ydb/core/tx/schemeshard/ut_helpers/helpers.h
+++ b/ydb/core/tx/schemeshard/ut_helpers/helpers.h
@@ -686,14 +686,6 @@ namespace NSchemeShardUT_Private {
const TString& user, NLoginProto::ESaslAuthMech::SaslAuthMech authMech,
NLoginProto::EHashType::HashType hashType, const TString& hash, const TString& authMessage = "");
- NKikimrScheme::TEvLoginResult LoginFinalize(
- TTestActorRuntime& runtime,
- const NLogin::TLoginProvider::TLoginUserRequest& request,
- const NLogin::TLoginProvider::TPasswordCheckResult& checkResult,
- const TString& passwordHash,
- const bool needUpdateCache
- );
-
void ModifyUser(TTestActorRuntime& runtime, ui64 txId, const TString& database, std::function<void(::NKikimrSchemeOp::TLoginModifyUser*)>&& initiator);
void ChangeIsEnabledUser(TTestActorRuntime& runtime, ui64 txId, const TString& database,
diff --git a/ydb/core/tx/schemeshard/ut_login/ut_login.cpp b/ydb/core/tx/schemeshard/ut_login/ut_login.cpp
index 8a3bdb298ef..64f591924e0 100644
--- a/ydb/core/tx/schemeshard/ut_login/ut_login.cpp
+++ b/ydb/core/tx/schemeshard/ut_login/ut_login.cpp
@@ -61,6 +61,29 @@ void CheckToken(const TString& token, const NKikimrScheme::TEvDescribeSchemeResu
UNIT_ASSERT_VALUES_EQUAL(validateResult.User, expectedUsername);
}
+void TestIsAdmin(const TVector<TString>& admins, const TString& testUser, bool isAdmin) {
+ TTestBasicRuntime runtime;
+ if (!admins.empty()) {
+ runtime.AddAppDataInit([&admins](ui32, NKikimr::TAppData& appData){
+ for (const auto& admin : admins) {
+ appData.AdministrationAllowedSIDs.emplace_back(admin);
+ }
+ });
+ }
+ TTestEnv env(runtime);
+ ui64 txId = 100;
+
+ const auto userHashes = MakeTestPasswordHashes("password1");
+ CreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", testUser, userHashes.HashedPassword);
+
+ const auto resultLogin = Login(runtime, testUser, NLoginProto::ESaslAuthMech::Plain,
+ NLoginProto::EHashType::ScramSha256, userHashes.ScramServerKey);
+ UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
+ auto describe = DescribePath(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
+ CheckToken(resultLogin.token(), describe, testUser);
+ UNIT_ASSERT_VALUES_EQUAL(resultLogin.GetIsAdmin(), isAdmin);
+}
+
} // namespace NSchemeShardUT_Private
Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
@@ -1036,77 +1059,10 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
reboot();
loginUser("");
}
-}
-
-Y_UNIT_TEST_SUITE(TSchemeShardLoginFinalize) {
-
- void TestSuccess(const TVector<TString>& admins, const TString& testUser, bool isAdmin) {
- TTestBasicRuntime runtime;
- if (!admins.empty()) {
- runtime.AddAppDataInit([&admins](ui32, NKikimr::TAppData& appData){
- for (const auto& admin : admins) {
- appData.AdministrationAllowedSIDs.emplace_back(admin);
- }
- });
- }
- TTestEnv env(runtime);
- ui64 txId = 100;
-
- const auto userHashes = MakeTestPasswordHashes("password1");
- CreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", testUser, userHashes.HashedPassword);
-
- const auto check = NLogin::TLoginProvider::TPasswordCheckResult{.Status =
- NLogin::TLoginProvider::TPasswordCheckResult::EStatus::SUCCESS};
- const auto request = NLogin::TLoginProvider::TLoginUserRequest({.User = testUser});
- // public keys are filled after the first login
- UNIT_ASSERT_VALUES_EQUAL(Login(runtime, testUser, NLoginProto::ESaslAuthMech::Plain, NLoginProto::EHashType::ScramSha256,
- MakeTestPasswordHashes("wrong-password1").ScramServerKey).error(), "Invalid password");
- const auto resultLogin = LoginFinalize(runtime, request, check, "", false);
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
- auto describe = DescribePath(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
- CheckToken(resultLogin.token(), describe, testUser);
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.GetIsAdmin(), isAdmin);
- }
-
- Y_UNIT_TEST(NoPublicKeys) {
- TTestBasicRuntime runtime;
- TTestEnv env(runtime);
- ui64 txId = 100;
-
- const auto user1Hashes = MakeTestPasswordHashes("password1");
- CreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user1", user1Hashes.HashedPassword);
-
- NLogin::TLoginProvider::TPasswordCheckResult check;
- check.FillInvalidPassword();
- const auto request = NLogin::TLoginProvider::TLoginUserRequest({.User = "user1"});
- const auto resultLogin = LoginFinalize(runtime, request, check, "", false);
- // public keys are filled after the first login
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "No key to generate token");
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.token(), "");
- }
-
- Y_UNIT_TEST(InvalidPassword) {
- TTestBasicRuntime runtime;
- TTestEnv env(runtime);
- ui64 txId = 100;
-
- const auto user1Hashes = MakeTestPasswordHashes("password1");
- CreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user1", user1Hashes.HashedPassword);
-
- NLogin::TLoginProvider::TPasswordCheckResult check;
- check.FillInvalidPassword();
- const auto request = NLogin::TLoginProvider::TLoginUserRequest({.User = "user1"});
- // public keys are filled after the first login
- UNIT_ASSERT_VALUES_EQUAL(Login(runtime, "user1", NLoginProto::ESaslAuthMech::Plain, NLoginProto::EHashType::ScramSha256,
- user1Hashes.ScramServerKey).error(), "");
- const auto resultLogin = LoginFinalize(runtime, request, check, "", false);
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "Invalid password");
- UNIT_ASSERT_VALUES_EQUAL(resultLogin.token(), "");
- }
- Y_UNIT_TEST(Success) {
- TestSuccess({}, "user1", true);
- TestSuccess({"user-admin"}, "user1", false);
- TestSuccess({"user1"}, "user1", true);
+ Y_UNIT_TEST(AdminLogin) {
+ TestIsAdmin( /* admins */ {}, /* testUser */ "user1", /* isAdmin */ true);
+ TestIsAdmin( /* admins */ {"user-admin"}, /* testUser */ "user1", /* isAdmin */ false);
+ TestIsAdmin( /* admins */ {"user1"}, /* testUser */ "user1", /* isAdmin */ true);
}
}
diff --git a/ydb/core/tx/schemeshard/ya.make b/ydb/core/tx/schemeshard/ya.make
index 78d45debc4a..2e22cd9a506 100644
--- a/ydb/core/tx/schemeshard/ya.make
+++ b/ydb/core/tx/schemeshard/ya.make
@@ -113,7 +113,6 @@ SRCS(
schemeshard__local_index_migration.cpp
schemeshard__local_index_migration.h
schemeshard__login.cpp
- schemeshard__login_finalize.cpp
schemeshard__make_access_database_no_inheritable.cpp
schemeshard__monitoring.cpp
schemeshard__monitoring.h
@@ -243,7 +242,6 @@ SRCS(
schemeshard__unmark_restore_tables.cpp
schemeshard__upgrade_access_database.cpp
schemeshard__upgrade_schema.cpp
- schemeshard__user_hashes_migration.cpp
schemeshard_audit_log.cpp
schemeshard_audit_log_fragment.cpp
schemeshard_backup.cpp
@@ -300,8 +298,6 @@ SRCS(
schemeshard_import_scheme_query_executor.cpp
schemeshard_info_types.cpp
schemeshard_info_types.h
- schemeshard_login_helper.cpp
- schemeshard_login_helper.h
schemeshard_path.cpp
schemeshard_path.h
schemeshard_path_describer.cpp
diff --git a/ydb/library/login/cache/lru.cpp b/ydb/library/login/cache/lru.cpp
deleted file mode 100644
index 7d9e17c52bf..00000000000
--- a/ydb/library/login/cache/lru.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "lru.h"
-
-namespace NLogin {
-
-TLruCache::TLruCache(std::size_t capacity)
- : Capacity(capacity)
-{
- Index.reserve(Capacity);
-}
-
-TLruCache::TIterator TLruCache::Find(const TKey& key) {
- const auto indexIt = Index.find(key);
- if (indexIt == Index.end()) {
- return Data.end();
- }
-
- Promote(indexIt->second);
- return indexIt->second;
-}
-
-std::pair<TLruCache::TIterator, bool> TLruCache::Insert(const TKey& key, bool value) {
- const auto indexIt = Index.find(key);
- if (indexIt != Index.end()) {
- Promote(indexIt->second);
- return std::make_pair(indexIt->second, false);
- }
-
- if (Capacity == 0) {
- return std::make_pair(Data.end(), false);
- }
-
- while (IsOverflow()) {
- Evict();
- }
-
- Data.push_front(std::make_pair(key, value));
- Index.emplace(key, Data.begin());
- return std::make_pair(Data.begin(), true);
-}
-
-std::size_t TLruCache::Size() const {
- return Index.size();
-}
-
-TLruCache::TIterator TLruCache::End() {
- return Data.end();
-}
-
-void TLruCache::Clear() {
- Data.clear();
- Index.clear();
-}
-
-bool TLruCache::IsOverflow() const {
- return Index.size() == Capacity;
-}
-
-void TLruCache::Promote(const TIterator it) {
- Data.splice(Data.begin(), Data, it);
-}
-
-void TLruCache::Evict() {
- const auto item = Data.back();
- Data.pop_back();
- Index.erase(item.first);
-}
-
-void TLruCache::Resize(size_t capacity) {
- Capacity = capacity;
- while (Index.size() > Capacity) {
- Evict();
- }
-}
-
-} // NLogin
diff --git a/ydb/library/login/cache/lru.h b/ydb/library/login/cache/lru.h
deleted file mode 100644
index b64ccdf5b69..00000000000
--- a/ydb/library/login/cache/lru.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-
-#include <list>
-#include <unordered_map>
-
-#include <util/generic/string.h>
-#include <util/string/builder.h>
-#include <util/str_stl.h>
-
-namespace NLogin {
-
-class TLruCache {
-public:
- struct TKey {
- TString User;
- TString Password;
- TString Hash;
-
- bool operator == (const TKey& other) const {
- return ((this->User == other.User) && (this->Password == other.Password) && (this->Hash == other.Hash));
- }
- };
-
- struct TKeyHash {
- size_t operator() (const TKey& key) const {
- return THash<TString>()(TStringBuilder() << key.User << key.Password << key.Hash);
- }
- };
-
- using TItem = std::pair<const TKey, bool>;
- using TDataContainer = std::list<TItem>;
- using TIterator = TDataContainer::iterator;
- using TIndexContainer = std::unordered_map<TKey, const TIterator, TKeyHash>;
-
- TLruCache(std::size_t capacity);
-
- TIterator Find(const TKey& key);
- std::pair<TIterator, bool> Insert(const TKey& key, bool value);
- std::size_t Size() const;
- TIterator End();
- void Clear();
- void Resize(size_t capacity);
-
-private:
- bool IsOverflow() const;
- void Promote(const TIterator it);
- void Evict();
-
-private:
- std::size_t Capacity = 0;
- TDataContainer Data;
- TIndexContainer Index;
-};
-
-} // NLogin
diff --git a/ydb/library/login/cache/lru_ut.cpp b/ydb/library/login/cache/lru_ut.cpp
deleted file mode 100644
index d3f550129dc..00000000000
--- a/ydb/library/login/cache/lru_ut.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <library/cpp/testing/unittest/registar.h>
-#include "lru.h"
-
-Y_UNIT_TEST_SUITE(TCacheTest) {
- Y_UNIT_TEST(TestLruCache) {
- NLogin::TLruCache cache(2);
- const NLogin::TLruCache::TKey user1 = {.User = "user1", .Password = "pass1", .Hash = "12345"};
- const NLogin::TLruCache::TKey user2 = {.User = "user2", .Password = "pass2", .Hash = "67890"};
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- {
- const auto insertResult = cache.Insert(user1, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- {
- const auto insertResult = cache.Insert(user2, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- {
- const auto it = cache.Find(user1);
- UNIT_ASSERT(it != cache.End());
- UNIT_ASSERT_EQUAL(it->second, true);
- }
- const NLogin::TLruCache::TKey user3 = {.User = "user3", .Password = "pass3", .Hash = "abcd"};
- // user2 must be evicted
- {
- const auto insertResult = cache.Insert(user3, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- {
- const auto it = cache.Find(user2);
- UNIT_ASSERT(it == cache.End());
- }
- {
- const auto it = cache.Find(user3);
- UNIT_ASSERT(it != cache.End());
- UNIT_ASSERT_EQUAL(it->second, true);
- }
- const NLogin::TLruCache::TKey user4 = {.User = "user4", .Password = "pass4", .Hash = "fedcba"};
- // user1 must be evicted
- {
- const auto insertResult = cache.Insert(user4, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- {
- const auto it = cache.Find(user1);
- UNIT_ASSERT(it == cache.End());
- }
- {
- const auto it = cache.Find(user4);
- UNIT_ASSERT(it != cache.End());
- UNIT_ASSERT_EQUAL(it->second, true);
- }
- cache.Clear();
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- }
-
- Y_UNIT_TEST(TestLruCacheWithEmptyCapacity) {
- NLogin::TLruCache cache(0);
- const NLogin::TLruCache::TKey user1 = {.User = "user1", .Password = "pass1", .Hash = "12345"};
- const NLogin::TLruCache::TKey user2 = {.User = "user2", .Password = "pass2", .Hash = "67890"};
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- {
- const auto insertResult = cache.Insert(user1, true);
- UNIT_ASSERT_EQUAL(insertResult.second, false);
- UNIT_ASSERT(insertResult.first == cache.End());
- }
- {
- const auto insertResult = cache.Insert(user2, true);
- UNIT_ASSERT_EQUAL(insertResult.second, false);
- UNIT_ASSERT(insertResult.first == cache.End());
- }
- }
-
- Y_UNIT_TEST(TestLruCacheWithSameUserAndPassword) {
- NLogin::TLruCache cache(2);
- const NLogin::TLruCache::TKey key1 = {.User = "user1", .Password = "pass1", .Hash = "12345"};
- const NLogin::TLruCache::TKey key2 = {.User = "user1", .Password = "pass1", .Hash = "67890"};
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- {
- const auto insertResult = cache.Insert(key1, false); // Bad password
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- {
- const auto insertResult = cache.Insert(key2, true); // Good password
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- }
-
- Y_UNIT_TEST(TestLruCacheWithDifferentPasswords) {
- NLogin::TLruCache cache(2);
- const NLogin::TLruCache::TKey key1 = {.User = "user1", .Password = "pass1", .Hash = "12345"};
- const NLogin::TLruCache::TKey key2 = {.User = "user1", .Password = "pass2", .Hash = "12345"};
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- {
- const auto insertResult = cache.Insert(key1, false); // Bad password
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- {
- const auto insertResult = cache.Insert(key2, true); // Good password
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- }
-
- Y_UNIT_TEST(TestLruCacheResize) {
- NLogin::TLruCache cache(2);
- const NLogin::TLruCache::TKey user1 = {.User = "user1", .Password = "pass1", .Hash = "12345"};
- const NLogin::TLruCache::TKey user2 = {.User = "user2", .Password = "pass2", .Hash = "67890"};
- UNIT_ASSERT_EQUAL(cache.Size(), 0);
- {
- const auto insertResult = cache.Insert(user1, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- {
- const auto insertResult = cache.Insert(user2, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
- const NLogin::TLruCache::TKey user3 = {.User = "user3", .Password = "pass3", .Hash = "abcdef"};
- {
- const auto insertResult = cache.Insert(user3, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 2);
-
- // Resize
- cache.Resize(5);
- {
- // return user1 to cache
- const auto insertResult = cache.Insert(user1, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- const NLogin::TLruCache::TKey user4 = {.User = "user4", .Password = "pass4", .Hash = "abcde4"};
- {
- const auto insertResult = cache.Insert(user4, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- const NLogin::TLruCache::TKey user5 = {.User = "user5", .Password = "pass5", .Hash = "abcde5"};
- {
- const auto insertResult = cache.Insert(user5, true);
- UNIT_ASSERT_EQUAL(insertResult.second, true);
- UNIT_ASSERT(insertResult.first != cache.End());
- }
- UNIT_ASSERT_EQUAL(cache.Size(), 5);
-
- // Resize
- cache.Resize(3);
- UNIT_ASSERT_EQUAL(cache.Size(), 3);
- {
- const auto it = cache.Find(user3);
- UNIT_ASSERT(it == cache.End());
- }
- {
- const auto it = cache.Find(user2);
- UNIT_ASSERT(it == cache.End());
- }
- }
-}
diff --git a/ydb/library/login/cache/ut/ya.make b/ydb/library/login/cache/ut/ya.make
deleted file mode 100644
index c36c19ff5b6..00000000000
--- a/ydb/library/login/cache/ut/ya.make
+++ /dev/null
@@ -1,9 +0,0 @@
-UNITTEST_FOR(ydb/library/login/cache)
-
-PEERDIR()
-
-SRCS(
- lru_ut.cpp
-)
-
-END()
diff --git a/ydb/library/login/cache/ya.make b/ydb/library/login/cache/ya.make
deleted file mode 100644
index 65ded9a4884..00000000000
--- a/ydb/library/login/cache/ya.make
+++ /dev/null
@@ -1,13 +0,0 @@
-LIBRARY()
-
-PEERDIR()
-
-SRCS(
- lru.cpp
-)
-
-END()
-
-RECURSE_FOR_TESTS(
- ut
-)
diff --git a/ydb/library/login/hashes_checker/hashes_checker.cpp b/ydb/library/login/hashes_checker/hashes_checker.cpp
index 12bccaed676..23586018f90 100644
--- a/ydb/library/login/hashes_checker/hashes_checker.cpp
+++ b/ydb/library/login/hashes_checker/hashes_checker.cpp
@@ -54,39 +54,6 @@ TArgonSecret ParseArgonHash(const TStringBuf argonHash) {
return { std::move(salt), std::move(hash) };
}
-TMaybe<TString> ArgonHashToNewFormat(const TStringBuf oldArgonHash) {
- NJson::TJsonValue json;
- if (!NJson::ReadJsonTree(oldArgonHash, &json)) {
- return Nothing();
- }
-
- if (!json.Has("type") || !json.Has("salt") || !json.Has("hash") || json["type"] != "argon2id") {
- return Nothing();
- }
-
- return json["salt"].GetString() + "$" + json["hash"].GetString();
-}
-
-TString HashedPasswordFromNewArgonHashFormat(const TString& argonHash) {
- NJson::TJsonValue hashes;
- hashes["argon2id"] = argonHash;
- hashes["version"] = HASHES_JSON_SCHEMA_VERSION;
- return Base64Encode(NJson::WriteJson(hashes, false));
-}
-
-TMaybe<TString> ArgonHashToOldFormat(const TStringBuf newArgonHash) {
- auto argonSecret = ParseArgonHash(newArgonHash);
- if (argonSecret.Salt.empty() || argonSecret.Hash.empty()) {
- return Nothing();
- }
-
- NJson::TJsonValue json;
- json["type"] = "argon2id";
- json["salt"] = std::move(argonSecret.Salt);
- json["hash"] = std::move(argonSecret.Hash);
- return NJson::WriteJson(json, false);
-}
-
bool IsOldFormatHash(const TString& hash) {
return THashesChecker::OldFormatCheck(hash).Success;
}
diff --git a/ydb/library/login/hashes_checker/hashes_checker.h b/ydb/library/login/hashes_checker/hashes_checker.h
index e61774fc7da..b7031c7b305 100644
--- a/ydb/library/login/hashes_checker/hashes_checker.h
+++ b/ydb/library/login/hashes_checker/hashes_checker.h
@@ -37,9 +37,6 @@ struct TScramSecret {
TString ServerKey;
};
-TMaybe<TString> ArgonHashToNewFormat(const TStringBuf oldArgonHash);
-TString HashedPasswordFromNewArgonHashFormat(const TString& argonHash);
-TMaybe<TString> ArgonHashToOldFormat(const TStringBuf newArgonHash);
bool IsOldFormatHash(const TString& hash);
TString ConvertOldFormatHash(const TString& oldFormatHash);
diff --git a/ydb/library/login/login.cpp b/ydb/library/login/login.cpp
index 4be301bcb73..39e28404904 100644
--- a/ydb/library/login/login.cpp
+++ b/ydb/library/login/login.cpp
@@ -34,19 +34,10 @@ namespace NLogin {
struct TLoginProvider::TImpl {
public:
- TLruCache SuccessPasswordsCache;
- TLruCache WrongPasswordsCache;
- std::function<bool()> IsCacheUsed = [] () {return false;};
static const THolder<const NArgonish::IArgon2Base> ArgonHasher;
public:
- TImpl() : TImpl([] () {return false;}, {}) {}
-
- TImpl(const std::function<bool()>& isCacheUsed, const TLoginProvider::TCacheSettings& cacheSettings)
- : SuccessPasswordsCache(cacheSettings.SuccessPasswordsCacheCapacity)
- , WrongPasswordsCache(cacheSettings.WrongPasswordsCacheCapacity)
- , IsCacheUsed(isCacheUsed)
- {}
+ TImpl() = default;
void GenerateKeyPair(TString& publicKey, TString& privateKey) const ;
TString GenerateArgonHash(const TString& password) const;
@@ -55,14 +46,6 @@ public:
static bool SaslPlainVerifyScramHash(const TString& serverKeyToVerify, const TString& storedHashValues);
static bool SaslScramVerifyHash(const TString& hashName, const TString& clientProof, const TString& authMessage, const TString& storedHashValues);
static TString SaslScramComputeServerSignature(const TString& hashName, const TString& authMessage, const TString& storedHashValues);
- bool VerifyHashValues(const TString& password, const TString& hash);
- bool NeedVerifyHash(const TLruCache::TKey& key, TPasswordCheckResult* checkResult);
- void UpdateCache(const TLruCache::TKey& key, const bool isSuccessVerifying);
-
- void UpdateCacheSettings(const TLoginProvider::TCacheSettings& cacheSettings);
-
-private:
- void ClearCache();
};
const THolder<const NArgonish::IArgon2Base> TLoginProvider::TImpl::ArgonHasher = Default<NArgonish::TArgon2Factory>().Create(
@@ -79,14 +62,12 @@ TLoginProvider::TLoginProvider()
{}
TLoginProvider::TLoginProvider(const TAccountLockout::TInitializer& accountLockoutInitializer)
- : TLoginProvider(TPasswordComplexity(), accountLockoutInitializer, [] () {return false;}, {})
+ : TLoginProvider(TPasswordComplexity(), accountLockoutInitializer)
{}
TLoginProvider::TLoginProvider(const TPasswordComplexity& passwordComplexity,
- const TAccountLockout::TInitializer& accountLockoutInitializer,
- const std::function<bool()>& isCacheUsed,
- const TCacheSettings& cacheSettings)
- : Impl(new TImpl(isCacheUsed, cacheSettings))
+ const TAccountLockout::TInitializer& accountLockoutInitializer)
+ : Impl(new TImpl())
, PasswordChecker(passwordComplexity)
, AccountLockout(accountLockoutInitializer)
{}
@@ -133,19 +114,11 @@ bool TLoginProvider::CheckHashes(const TString& hashedPassword, TString& error)
return true;
}
-bool TLoginProvider::CheckPasswordOrArgonHash(bool IsHashedPassword, const TString& user, const TString& password, TString& error) const {
- if (IsHashedPassword) {
- auto hashCheckResult = THashesChecker::OldFormatCheck(password);
- if (!hashCheckResult.Success) {
- error = hashCheckResult.Error;
- return false;
- }
- } else {
- auto passwordCheckResult = PasswordChecker.Check(user, password);
- if (!passwordCheckResult.Success) {
- error = passwordCheckResult.Error;
- return false;
- }
+bool TLoginProvider::CheckPassword(const TString& user, const TString& password, TString& error) const {
+ auto passwordCheckResult = PasswordChecker.Check(user, password);
+ if (!passwordCheckResult.Success) {
+ error = passwordCheckResult.Error;
+ return false;
}
return true;
@@ -163,10 +136,10 @@ TLoginProvider::TBasicResponse TLoginProvider::CreateUser(const TCreateUserReque
if (!CheckHashes(request.HashedPassword, response.Error)) {
return response;
}
- }
-
- if (!CheckPasswordOrArgonHash(request.IsHashedPassword, request.User, request.Password, response.Error)) {
- return response;
+ } else {
+ if (!CheckPassword(request.User, request.Password, response.Error)) {
+ return response;
+ }
}
auto itUserCreate = Sids.emplace(request.User, TSidRecord{.Type = NLoginProto::ESidType::USER});
@@ -183,11 +156,10 @@ TLoginProvider::TBasicResponse TLoginProvider::CreateUser(const TCreateUserReque
user.Name = request.User;
user.CreatedAt = std::chrono::system_clock::now();
user.IsEnabled = request.CanLogin;
- user.ArgonHash = request.IsHashedPassword ? request.Password : Impl->GenerateArgonHash(request.Password);
if (request.HashedPassword) {
user.PasswordHashes = request.HashedPassword;
} else {
- user.PasswordHashes = HashedPasswordFromNewArgonHashFormat(*ArgonHashToNewFormat(user.ArgonHash));
+ user.PasswordHashes = Impl->GenerateArgonHash(request.Password);
}
user.FillHashStorage();
@@ -222,23 +194,17 @@ TLoginProvider::TBasicResponse TLoginProvider::ModifyUser(const TModifyUserReque
if (!CheckHashes(*request.HashedPassword, response.Error)) {
return response;
}
- }
-
- if (request.Password.has_value()) {
- if (!CheckPasswordOrArgonHash(request.IsHashedPassword, request.User, request.Password.value(), response.Error)) {
+ } else if (request.Password.has_value()) {
+ if (!CheckPassword(request.User, request.Password.value(), response.Error)) {
return response;
}
}
- if (request.Password.has_value()) {
- user.ArgonHash = request.IsHashedPassword ? request.Password.value() : Impl->GenerateArgonHash(request.Password.value());
- }
-
if (request.HashedPassword.has_value()) {
user.PasswordHashes = request.HashedPassword.value();
user.FillHashStorage();
} else if (request.Password.has_value()) {
- user.PasswordHashes = HashedPasswordFromNewArgonHashFormat(*ArgonHashToNewFormat(user.ArgonHash));
+ user.PasswordHashes = Impl->GenerateArgonHash(request.Password.value());
user.FillHashStorage();
}
@@ -555,29 +521,24 @@ bool TLoginProvider::NeedVerifyHash(const TLoginUserRequest& request, TPasswordC
return false;
}
- if (request.HashToValidate.has_value()) {
- const auto& hashToValidate = *request.HashToValidate;
- switch (hashToValidate.AuthMech) {
- case NLoginProto::ESaslAuthMech::Plain:
- case NLoginProto::ESaslAuthMech::Scram: {
- auto itHashRecord = sid->HashStorage.find(hashToValidate.HashType);
- if (itHashRecord == sid->HashStorage.end()) {
- checkResult->FillInvalidHashType();
- return false;
- }
-
- *hashValues = itHashRecord->second.HashValues;
- return true;
- }
- default: {
- checkResult->FillUnsupportedSaslMech();
+ Y_ENSURE(request.HashToValidate.has_value());
+ const auto& hashToValidate = *request.HashToValidate;
+ switch (hashToValidate.AuthMech) {
+ case NLoginProto::ESaslAuthMech::Plain:
+ case NLoginProto::ESaslAuthMech::Scram: {
+ auto itHashRecord = sid->HashStorage.find(hashToValidate.HashType);
+ if (itHashRecord == sid->HashStorage.end()) {
+ checkResult->FillInvalidHashType();
return false;
}
- }
- } else if (request.Password.has_value()) {
- *hashValues = sid->ArgonHash;
- return Impl->NeedVerifyHash({.User = request.User, .Password = *request.Password, .Hash = sid->ArgonHash}, checkResult);
+ *hashValues = itHashRecord->second.HashValues;
+ return true;
+ }
+ default: {
+ checkResult->FillUnsupportedSaslMech();
+ return false;
+ }
}
}
@@ -611,7 +572,7 @@ void TLoginProvider::VerifyHashValues(const TLoginUserRequest& request, TPasswor
return;
}
}
- };
+ }
case NLoginProto::ESaslAuthMech::Scram: {
const auto& hashTypeDescr = HashesRegistry.HashTypesMap.at(hashToValidate.HashType);
if (!TImpl::SaslScramVerifyHash(hashTypeDescr.Name, hashToValidate.Hash, hashToValidate.AuthMessage, hashValues)) {
@@ -629,14 +590,6 @@ void TLoginProvider::VerifyHashValues(const TLoginUserRequest& request, TPasswor
}
}
-bool TLoginProvider::VerifyArgonHash(const TLoginUserRequest& request, const TString& passwordHash) {
- return TImpl::VerifyArgonHash(*request.Password, passwordHash);
-}
-
-void TLoginProvider::UpdateCache(const TLoginUserRequest& request, const TString& passwordHash, const bool isSuccessVerifying) {
- Impl->UpdateCache({.User = request.User, .Password = *request.Password, .Hash = passwordHash}, isSuccessVerifying);
-}
-
bool TLoginProvider::FillUnavailableKey(TPasswordCheckResult* checkResult) const {
if (Keys.empty() || Keys.back().PrivateKey.empty()) {
checkResult->FillUnavailableKey();
@@ -750,15 +703,8 @@ TLoginProvider::TLoginUserResponse TLoginProvider::LoginUser(const TLoginUserReq
TPasswordCheckResult checkResult;
TString hashValues;
if (NeedVerifyHash(request, &checkResult, &hashValues)) {
- if (request.HashToValidate.has_value()) {
- VerifyHashValues(request, &checkResult, hashValues);
- } else if (request.Password.has_value()) { // for backward compatibility
- const auto isSuccessVerifying = VerifyArgonHash(request, hashValues);
- UpdateCache(request, hashValues, isSuccessVerifying);
- if (!isSuccessVerifying) {
- checkResult.FillInvalidPassword();
- }
- }
+ Y_ENSURE(request.HashToValidate.has_value());
+ VerifyHashValues(request, &checkResult, hashValues);
}
return LoginUser(request, checkResult);
@@ -964,43 +910,28 @@ void TLoginProvider::TImpl::GenerateKeyPair(TString& publicKey, TString& private
}
TString TLoginProvider::TImpl::GenerateArgonHash(const TString& password) const {
- TString hashType = "argon2id";
+ const TString hashType = "argon2id";
const auto& hashDescription = HashesRegistry.HashNamesMap.at(hashType);
- char salt[hashDescription.SaltSize];
- char hash[hashDescription.HashSize];
- RAND_bytes(reinterpret_cast<unsigned char*>(salt), hashDescription.SaltSize);
+ std::string salt;
+ salt.resize(hashDescription.SaltSize);
+ std::string hash;
+ hash.resize(hashDescription.HashSize);
+ RAND_bytes(reinterpret_cast<unsigned char*>(salt.data()), salt.size());
ArgonHasher->Hash(
reinterpret_cast<const ui8*>(password.data()),
password.size(),
- reinterpret_cast<ui8*>(salt),
- hashDescription.SaltSize,
- reinterpret_cast<ui8*>(hash),
- hashDescription.HashSize);
- NJson::TJsonValue json;
- json["type"] = std::move(hashType);
- json["salt"] = Base64Encode(TStringBuf(salt, hashDescription.SaltSize));
- json["hash"] = Base64Encode(TStringBuf(hash, hashDescription.HashSize));
- return NJson::WriteJson(json, false);
-}
-
-bool TLoginProvider::TImpl::VerifyArgonHash(const TString& password, const TString& passwordHash) {
- NJson::TJsonValue json;
- if (!NJson::ReadJsonTree(passwordHash, &json)) {
- return false;
- }
- TString type = json["type"].GetStringRobust();
- if (type != "argon2id") {
- return false;
- }
- TString salt = Base64Decode(json["salt"].GetStringRobust());
- TString hash = Base64Decode(json["hash"].GetStringRobust());
- return ArgonHasher->Verify(
- reinterpret_cast<const ui8*>(password.data()),
- password.size(),
- reinterpret_cast<const ui8*>(salt.data()),
+ reinterpret_cast<ui8*>(salt.data()),
salt.size(),
- reinterpret_cast<const ui8*>(hash.data()),
+ reinterpret_cast<ui8*>(hash.data()),
hash.size());
+
+ std::stringstream secret;
+ secret << Base64Encode(salt) << '$' << Base64Encode(hash);
+
+ NJson::TJsonValue hashes;
+ hashes[hashType] = secret.str();
+ hashes["version"] = HASHES_JSON_SCHEMA_VERSION;
+ return Base64Encode(NJson::WriteJson(hashes, false));
}
bool TLoginProvider::TImpl::SaslPlainVerifyArgonHash(const TString& hashToVerify, const TString& storedHashValue) {
@@ -1036,50 +967,6 @@ TString TLoginProvider::TImpl::SaslScramComputeServerSignature(const TString& ha
return Base64Encode(serverSignature);
}
-bool TLoginProvider::TImpl::NeedVerifyHash(const TLruCache::TKey& key, TPasswordCheckResult* checkResult) {
- Y_ENSURE(checkResult);
-
- if (!IsCacheUsed()) {
- ClearCache();
- return true;
- }
-
- if (SuccessPasswordsCache.Find(key) != SuccessPasswordsCache.End()) {
- checkResult->Status = TLoginUserResponse::EStatus::SUCCESS;
- return false;
- }
-
- if (WrongPasswordsCache.Find(key) != WrongPasswordsCache.End()) {
- checkResult->FillInvalidPassword();
- return false;
- }
-
- return true;
-}
-
-void TLoginProvider::TImpl::UpdateCache(const TLruCache::TKey& key, const bool isSuccessVerifying) {
- if (isSuccessVerifying) {
- SuccessPasswordsCache.Insert(key, true);
- } else {
- WrongPasswordsCache.Insert(key, false);
- }
-
-}
-
-void TLoginProvider::TImpl::UpdateCacheSettings(const TCacheSettings& cacheSettings) {
- SuccessPasswordsCache.Resize(cacheSettings.SuccessPasswordsCacheCapacity);
- WrongPasswordsCache.Resize(cacheSettings.WrongPasswordsCacheCapacity);
-}
-
-void TLoginProvider::TImpl::ClearCache() {
- if (SuccessPasswordsCache.Size() > 0) {
- SuccessPasswordsCache.Clear();
- }
- if (WrongPasswordsCache.Size() > 0) {
- WrongPasswordsCache.Clear();
- }
-}
-
NLoginProto::TSecurityState TLoginProvider::GetSecurityState() const {
NLoginProto::TSecurityState state;
state.SetAudience(Audience);
@@ -1145,14 +1032,8 @@ void TLoginProvider::UpdateSecurityState(const NLoginProto::TSecurityState& stat
TSidRecord& sid = Sids[pbSid.GetName()];
sid.Type = pbSid.GetType();
sid.Name = pbSid.GetName();
- sid.ArgonHash = pbSid.GetArgonHash();
if (pbSid.GetPasswordHashes()) {
sid.PasswordHashes = pbSid.GetPasswordHashes();
- } else if (pbSid.GetArgonHash()) {
- // ignore old hash format because we can't parse it
- if (const auto argonHashInNewFormat = ArgonHashToNewFormat(pbSid.GetArgonHash())) {
- sid.PasswordHashes = HashedPasswordFromNewArgonHashFormat(*argonHashInNewFormat);
- }
}
sid.FillHashStorage();
@@ -1189,8 +1070,4 @@ void TLoginProvider::UpdateAccountLockout(const TAccountLockout::TInitializer& a
AccountLockout.Update(accountLockoutInitializer);
}
-void TLoginProvider::UpdateCacheSettings(const TCacheSettings& settings) {
- Impl->UpdateCacheSettings(settings);
-}
-
}
diff --git a/ydb/library/login/login.h b/ydb/library/login/login.h
index 8611de5eb10..6baa5d03367 100644
--- a/ydb/library/login/login.h
+++ b/ydb/library/login/login.h
@@ -6,7 +6,6 @@
#include <deque>
#include <util/generic/string.h>
#include <ydb/library/login/account_lockout/account_lockout.h>
-#include <ydb/library/login/cache/lru.h>
#include <ydb/library/login/hashes_checker/hash_types.h>
#include <ydb/library/login/protos/login.pb.h>
#include <ydb/library/login/password_checker/password_checker.h>
@@ -26,9 +25,6 @@ public:
static constexpr const char* EXTERNAL_AUTH_CLAIM_NAME = "external_authentication";
static constexpr auto MAX_TOKEN_EXPIRE_TIME = std::chrono::hours(12);
- static constexpr size_t SUCCESS_PASSWORDS_CACHE_CAPACITY = 20;
- static constexpr size_t WRONG_PASSWORDS_CACHE_CAPACITY = 20;
-
struct TBasicRequest {};
struct TBasicResponse {
@@ -67,7 +63,6 @@ public:
};
TString User;
- std::optional<TString> Password;
std::optional<THashToValidate> HashToValidate;
std::optional<TString> ExternalAuth;
TOptions Options;
@@ -138,7 +133,6 @@ public:
TString User;
TString Password;
TString HashedPassword;
- bool IsHashedPassword = false;
bool CanLogin = true;
};
@@ -146,7 +140,6 @@ public:
TString User;
std::optional<TString> Password;
std::optional<TString> HashedPassword;
- bool IsHashedPassword = false;
std::optional<bool> CanLogin;
};
@@ -210,7 +203,6 @@ public:
ESidType::SidType Type = ESidType::UNKNOWN;
TString Name;
- TString ArgonHash;
TString PasswordHashes;
THashMap<NLoginProto::EHashType::HashType, THashRecord> HashStorage;
@@ -224,11 +216,6 @@ public:
void FillHashStorage();
};
- struct TCacheSettings {
- size_t SuccessPasswordsCacheCapacity = SUCCESS_PASSWORDS_CACHE_CAPACITY;
- size_t WrongPasswordsCacheCapacity = WRONG_PASSWORDS_CACHE_CAPACITY;
- };
-
// our current audience (database name)
TString Audience;
@@ -251,11 +238,8 @@ public:
// Login
TLoginUserResponse LoginUser(const TLoginUserRequest& request);
- // The next four methods are used (all together combined) when it's needed to separate hash verification which is quite cpu-intensive
bool NeedVerifyHash(const TLoginUserRequest& request, TPasswordCheckResult* checkResult, TString* hashValues);
void VerifyHashValues(const TLoginUserRequest& request, TPasswordCheckResult* checkResult, const TString& hashValues);
- static bool VerifyArgonHash(const TLoginUserRequest& request, const TString& passwordHash); // it's made static to be thread-safe
- void UpdateCache(const TLoginUserRequest& request, const TString& passwordHash, const bool isSuccessVerifying);
TLoginProvider::TLoginUserResponse LoginUser(const TLoginUserRequest& request, const TPasswordCheckResult& checkResult);
TValidateTokenResponse ValidateToken(const TValidateTokenRequest& request);
@@ -275,14 +259,11 @@ public:
void UpdatePasswordCheckParameters(const TPasswordComplexity& passwordComplexity);
const TPasswordComplexity& GetPasswordCheckParameters() const;
void UpdateAccountLockout(const TAccountLockout::TInitializer& accountLockoutInitializer);
- void UpdateCacheSettings(const TCacheSettings& settings);
TLoginProvider();
TLoginProvider(const TAccountLockout::TInitializer& accountLockoutInitializer);
TLoginProvider(const TPasswordComplexity& passwordComplexity,
- const TAccountLockout::TInitializer& accountLockoutInitializer,
- const std::function<bool()>& isCacheUsed,
- const TCacheSettings& cacheSettings);
+ const TAccountLockout::TInitializer& accountLockoutInitializer);
~TLoginProvider();
std::vector<TString> GetGroupsMembership(const TString& member) const;
@@ -305,7 +286,7 @@ private:
bool ShouldResetFailedAttemptCount(const TSidRecord& sid) const;
bool ShouldUnlockAccount(const TSidRecord& sid) const;
bool CheckHashes(const TString& hashedPassword, TString& error) const;
- bool CheckPasswordOrArgonHash(bool IsHashedPassword, const TString& user, const TString& password, TString& error) const;
+ bool CheckPassword(const TString& user, const TString& password, TString& error) const;
TSidRecord* GetUserSid(const TString& user);
bool FillUnavailableKey(TPasswordCheckResult* checkResult) const;
bool FillInvalidUser(const TSidRecord* sid, TPasswordCheckResult* checkResult) const;
diff --git a/ydb/library/login/login_ut.cpp b/ydb/library/login/login_ut.cpp
index 47872b2113b..b1ff60804c0 100644
--- a/ydb/library/login/login_ut.cpp
+++ b/ydb/library/login/login_ut.cpp
@@ -12,49 +12,53 @@ using namespace NLogin;
Y_UNIT_TEST_SUITE(Login) {
void none() {}
- Y_UNIT_TEST(TestSuccessfulLogin1) {
- TLoginProvider provider;
- provider.Audience = "test_audience1";
- provider.RotateKeys();
- TLoginProvider::TCreateUserRequest request1;
- request1.User = "user1";
- request1.Password = "password1";
- auto response1 = provider.CreateUser(request1);
- UNIT_ASSERT(!response1.Error);
- TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.Password = request1.Password;
- auto response2 = provider.LoginUser(request2);
- UNIT_ASSERT_VALUES_EQUAL(response2.Error, "");
- TLoginProvider::TValidateTokenRequest request3;
- request3.Token = response2.Token;
- auto response3 = provider.ValidateToken(request3);
- UNIT_ASSERT_VALUES_EQUAL(response3.Error, "");
- UNIT_ASSERT(response3.User == request1.User);
+ // Precomputed argon2id + SCRAM-SHA-256 hashes from scram_ut.cpp
+ // Password: "password1"
+ // Salt (base64): "s0QSrrFVkMTh3k2TTk860A=="
+ // Iterations: 4096
+ // StoredKey (base64): "LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo="
+ // ServerKey (base64): "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
+ static const TString PASSWORD1_HASHES = R"({
+ "version": 1,
+ "argon2id": "flbr3YnA9kG67qegwDTaYg==$wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=",
+ "scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
+ })";
+
+ // The ServerKey of the SCRAM-SHA-256 hash above
+ static const TString PASSWORD1_SCRAM_SERVER_KEY = "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc=";
+
+ // The Hash of the Argon2Id hash above
+ static const TString PASSWORD1_ARGON_HASH = "wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=";
+
+ static const TString AUTH_MESSAGE = "n=user,r=clientnonce,r=clientservernonce,s=s0QSrrFVkMTh3k2TTk860A==,i=4096,c=biws,r=clientservernonce";
+
+ // Precomputed ClientProof of the SCRAM-SHA-256 hash above and AUTH_MESSAGE
+ static const TString CLIENT_PROOF = "AJgthTHWf0jz/bMHwrWDOHk9SQPpPpvGx937mEzFnCQ=";
+
+ // Precomputed ServerSignature of the SCRAM-SHA-256 hash above and AUTH_MESSAGE
+ static const TString SERVER_SIGNATURE = "RBEDP7XfP9zTpxx+++HZSiw7kB7MDtfZ5mlBcMSxRQY=";
+
+ TLoginProvider::TLoginUserRequest MakeScramPlainLoginRequest(const TString& user, const TString& scramServerKey) {
+ TLoginProvider::TLoginUserRequest request;
+ request.User = user;
+
+ TLoginProvider::THashToValidate hashToValidate;
+ hashToValidate.AuthMech = NLoginProto::ESaslAuthMech::Plain;
+ hashToValidate.HashType = NLoginProto::EHashType::ScramSha256;
+ hashToValidate.Hash = scramServerKey;
+ request.HashToValidate = hashToValidate;
+
+ return request;
}
- Y_UNIT_TEST(TestSuccessfulLogin2) {
+ Y_UNIT_TEST(TestSuccessfulLogin1) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
- // Using precomputed SCRAM-SHA-256 values from scram_ut.cpp
- // Password: "password1"
- // Salt (base64): "s0QSrrFVkMTh3k2TTk860A=="
- // Iterations: 4096
- // StoredKey (base64): "LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo="
- // ServerKey (base64): "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
-
- TString hashes = R"(
- {
- "version": 1,
- "argon2id": "flbr3YnA9kG67qegwDTaYg==$wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=",
- "scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
- }
- )";
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.HashedPassword = Base64Encode(hashes);
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
@@ -62,7 +66,7 @@ Y_UNIT_TEST_SUITE(Login) {
TLoginProvider::THashToValidate hashToValidate1;
hashToValidate1.AuthMech = NLoginProto::ESaslAuthMech::Plain;
hashToValidate1.HashType = NLoginProto::EHashType::Argon;
- hashToValidate1.Hash = "wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=";
+ hashToValidate1.Hash = PASSWORD1_ARGON_HASH;
TLoginProvider::TLoginUserRequest request2;
request2.User = request1.User;
request2.HashToValidate = hashToValidate1;
@@ -70,38 +74,27 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(response2.Error, "");
// Test SCRAM-SHA-256 authentication with Plain mechanism (ServerKey validation)
- TLoginProvider::THashToValidate hashToValidate2;
- hashToValidate2.AuthMech = NLoginProto::ESaslAuthMech::Plain;
- hashToValidate2.HashType = NLoginProto::EHashType::ScramSha256;
- hashToValidate2.Hash = "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc=";
TLoginProvider::TLoginUserRequest request3;
- request3.User = request1.User;
- request3.HashToValidate = hashToValidate2;
+ request3 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
auto response3 = provider.LoginUser(request3);
UNIT_ASSERT_VALUES_EQUAL(response3.Error, "");
- // Test SCRAM-SHA-256 authentication with SCRAM mechanism using precomputed ClientProof
- TString authMessage = "n=user,r=clientnonce,r=clientservernonce,s=s0QSrrFVkMTh3k2TTk860A==,i=4096,c=biws,r=clientservernonce";
- TString clientProof = "AJgthTHWf0jz/bMHwrWDOHk9SQPpPpvGx937mEzFnCQ=";
-
- TLoginProvider::THashToValidate hashToValidate3;
- hashToValidate3.AuthMech = NLoginProto::ESaslAuthMech::Scram;
- hashToValidate3.HashType = NLoginProto::EHashType::ScramSha256;
- hashToValidate3.Hash = clientProof;
- hashToValidate3.AuthMessage = authMessage;
-
+ // Test SCRAM-SHA-256 authentication with SCRAM mechanism (ClientProof validation)
+ TLoginProvider::THashToValidate hashToValidate2;
+ hashToValidate2.AuthMech = NLoginProto::ESaslAuthMech::Scram;
+ hashToValidate2.HashType = NLoginProto::EHashType::ScramSha256;
+ hashToValidate2.Hash = CLIENT_PROOF;
+ hashToValidate2.AuthMessage = AUTH_MESSAGE;
TLoginProvider::TLoginUserRequest request4;
request4.User = request1.User;
- request4.HashToValidate = hashToValidate3;
+ request4.HashToValidate = hashToValidate2;
auto response4 = provider.LoginUser(request4);
UNIT_ASSERT_VALUES_EQUAL(response4.Error, "");
-
- // Verify server signature is also correct (from scram_ut.cpp)
- TString expectedServerSignature = "RBEDP7XfP9zTpxx+++HZSiw7kB7MDtfZ5mlBcMSxRQY=";
- UNIT_ASSERT_VALUES_EQUAL(response4.ServerSignature.value(), expectedServerSignature);
+ // Verify server signature is also correct
+ UNIT_ASSERT_VALUES_EQUAL(response4.ServerSignature.value(), SERVER_SIGNATURE);
}
- Y_UNIT_TEST(TestSuccessfulLogin3) {
+ Y_UNIT_TEST(TestSuccessfulLogin2) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
@@ -116,6 +109,7 @@ Y_UNIT_TEST_SUITE(Login) {
request1.HashedPassword = Base64Encode(hashes);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
+
TLoginProvider::THashToValidate hashToValidate;
hashToValidate.AuthMech = NLoginProto::ESaslAuthMech::Plain;
hashToValidate.HashType = NLoginProto::EHashType::Argon;
@@ -203,75 +197,48 @@ Y_UNIT_TEST_SUITE(Login) {
}
}
- Y_UNIT_TEST(TestWrongPassword1) {
- TLoginProvider provider;
- provider.RotateKeys();
- TLoginProvider::TCreateUserRequest request1;
- request1.User = "user1";
- request1.Password = "password1";
- auto response1 = provider.CreateUser(request1);
- UNIT_ASSERT(!response1.Error);
- TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.Password = "wrong password";
- auto response2 = provider.LoginUser(request2);
- UNIT_ASSERT(response2.Error == "Invalid password");
- }
-
- Y_UNIT_TEST(TestWrongPassword2) {
+ Y_UNIT_TEST(TestWrongPassword) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
- TString hashes1 = R"(
- {
- "version": 1,
- "argon2id": "flbr3YnA9kG67qegwDTaYg==$wsTryyX+vdkLiZ4PfYabvgVwHf8tbxBVVtDluhiz3fo=",
- "scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
- }
- )";
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.HashedPassword = Base64Encode(hashes1);
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
- // Test with wrong Argon hash (using ServerKey instead of Argon hash)
- TLoginProvider::THashToValidate hashToValidate;
- hashToValidate.AuthMech = NLoginProto::ESaslAuthMech::Plain;
- hashToValidate.HashType = NLoginProto::EHashType::Argon;
- hashToValidate.Hash = "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc=";
+ // Test with wrong Argon hash (using SCRAM-SHA-256 ServerKey instead of Argon hash)
+ TLoginProvider::THashToValidate hashToValidate1;
+ hashToValidate1.AuthMech = NLoginProto::ESaslAuthMech::Plain;
+ hashToValidate1.HashType = NLoginProto::EHashType::Argon;
+ hashToValidate1.Hash = PASSWORD1_SCRAM_SERVER_KEY;
TLoginProvider::TLoginUserRequest request2;
request2.User = request1.User;
- request2.HashToValidate = hashToValidate;
+ request2.HashToValidate = hashToValidate1;
auto response2 = provider.LoginUser(request2);
UNIT_ASSERT(response2.Error == "Invalid password");
// Test Plain authentication with wrong SCRAM-SHA-256 hash (using StoredKey instead of ServerKey)
- TLoginProvider::THashToValidate hashToValidate2;
- hashToValidate2.AuthMech = NLoginProto::ESaslAuthMech::Plain;
- hashToValidate2.HashType = NLoginProto::EHashType::ScramSha256;
- hashToValidate2.Hash = "LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=";
+ const TString wrongServerKey = "LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=";
+
TLoginProvider::TLoginUserRequest request3;
- request3.User = request1.User;
- request3.HashToValidate = hashToValidate2;
+ request3 = MakeScramPlainLoginRequest(request1.User, wrongServerKey);
auto response3 = provider.LoginUser(request3);
UNIT_ASSERT(response3.Error == "Invalid password");
// Test SCRAM authentication with wrong ClientProof
// Using ClientProof for "password2" instead of "password1"
- TString authMessage = "n=user,r=clientnonce,r=clientservernonce,s=s0QSrrFVkMTh3k2TTk860A==,i=4096,c=biws,r=clientservernonce";
- TString wrongClientProof = "onCT9KAMiTb4vvJzBQM0w1nXLW3hJiZIJuc9Jz71pV8=";
-
- TLoginProvider::THashToValidate hashToValidate3;
- hashToValidate3.AuthMech = NLoginProto::ESaslAuthMech::Scram;
- hashToValidate3.HashType = NLoginProto::EHashType::ScramSha256;
- hashToValidate3.Hash = wrongClientProof;
- hashToValidate3.AuthMessage = authMessage;
+ const TString wrongClientProof = "onCT9KAMiTb4vvJzBQM0w1nXLW3hJiZIJuc9Jz71pV8=";
+ TLoginProvider::THashToValidate hashToValidate2;
+ hashToValidate2.AuthMech = NLoginProto::ESaslAuthMech::Scram;
+ hashToValidate2.HashType = NLoginProto::EHashType::ScramSha256;
+ hashToValidate2.Hash = wrongClientProof;
+ hashToValidate2.AuthMessage = AUTH_MESSAGE;
TLoginProvider::TLoginUserRequest request4;
request4.User = request1.User;
- request4.HashToValidate = hashToValidate3;
+ request4.HashToValidate = hashToValidate2;
auto response4 = provider.LoginUser(request4);
UNIT_ASSERT(response4.Error == "Invalid password");
}
@@ -280,6 +247,7 @@ Y_UNIT_TEST_SUITE(Login) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
+
TString hashes1 = R"(
{
"version": 1,
@@ -291,39 +259,36 @@ Y_UNIT_TEST_SUITE(Login) {
request1.HashedPassword = Base64Encode(hashes1);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
- TLoginProvider::THashToValidate hashToValidate;
- hashToValidate.AuthMech = NLoginProto::ESaslAuthMech::Plain;
- hashToValidate.HashType = NLoginProto::EHashType::ScramSha256;
- hashToValidate.Hash = "eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc=";
+
TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.HashToValidate = hashToValidate;
+ request2 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
auto response2 = provider.LoginUser(request2);
UNIT_ASSERT_VALUES_EQUAL(response2.Error, "Invalid hash type");
+ TLoginProvider::THashToValidate hashToValidate;
hashToValidate.AuthMech = NLoginProto::ESaslAuthMech::Scram;
hashToValidate.HashType = NLoginProto::EHashType::ScramSha256;
hashToValidate.Hash = "clientproof";
hashToValidate.AuthMessage = "n=user1,r=nonce,r=nonceserver,c=biws,r=nonceserver";
-
TLoginProvider::TLoginUserRequest request3;
request3.User = request1.User;
request3.HashToValidate = hashToValidate;
- auto loginResponse = provider.LoginUser(request3);
- UNIT_ASSERT_VALUES_EQUAL(loginResponse.Error, "Invalid hash type");
+ auto response3 = provider.LoginUser(request3);
+ UNIT_ASSERT_VALUES_EQUAL(response3.Error, "Invalid hash type");
}
Y_UNIT_TEST(TestUnknownUser) {
TLoginProvider provider;
provider.RotateKeys();
+
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.Password = "password1";
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
+
TLoginProvider::TLoginUserRequest request2;
- request2.User = "wrong user";
- request2.Password = request1.Password;
+ request2 = MakeScramPlainLoginRequest("wrong user", PASSWORD1_SCRAM_SERVER_KEY);
auto response2 = provider.LoginUser(request2);
UNIT_ASSERT(response2.Error == "Invalid user");
}
@@ -331,21 +296,23 @@ Y_UNIT_TEST_SUITE(Login) {
Y_UNIT_TEST(TestRemovedUser) {
TLoginProvider provider;
provider.RotateKeys();
+
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.Password = "password1";
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
+
TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.Password = request1.Password;
+ request2 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
auto response2 = provider.LoginUser(request2);
UNIT_ASSERT_VALUES_EQUAL(response2.Error, "");
+
provider.RemoveUser(request1.User);
+
TLoginProvider::TLoginUserRequest request3;
- request3.User = request2.User;
- request3.Password = request2.Password;
- auto response3 = provider.LoginUser(request2);
+ request3 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
+ auto response3 = provider.LoginUser(request3);
UNIT_ASSERT(response3.Error == "Invalid user");
}
@@ -353,16 +320,18 @@ Y_UNIT_TEST_SUITE(Login) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
+
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.Password = "password1";
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
+
TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.Password = request1.Password;
+ request2 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
auto response2 = provider.LoginUser(request2);
UNIT_ASSERT(response2.Error.empty());
+
TLoginProvider::TValidateTokenRequest request3;
request3.Token = response2.Token;
provider.Audience = "test_audience2";
@@ -374,24 +343,23 @@ Y_UNIT_TEST_SUITE(Login) {
TLoginProvider provider;
provider.Audience = "test_audience1";
provider.RotateKeys();
- TLoginProvider::TCreateUserRequest createUser1Request {
- .User = "user1",
- .Password = "password1"
- };
- auto createUser1Response = provider.CreateUser(createUser1Request);
- UNIT_ASSERT(!createUser1Response.Error);
- TLoginProvider::TLoginUserRequest loginUser1Request1 {
- .User = createUser1Request.User,
- .Password = createUser1Request.Password
- };
- auto loginUser1Response1 = provider.LoginUser(loginUser1Request1);
- UNIT_ASSERT_VALUES_EQUAL(loginUser1Response1.Error, "");
- TLoginProvider::TValidateTokenRequest validateUser1TokenRequest1 {
- .Token = loginUser1Response1.Token
- };
- auto validateUser1TokenResponse1 = provider.ValidateToken(validateUser1TokenRequest1);
- UNIT_ASSERT_VALUES_EQUAL(validateUser1TokenResponse1.Error, "");
- UNIT_ASSERT(validateUser1TokenResponse1.User == createUser1Request.User);
+
+ TLoginProvider::TCreateUserRequest request1;
+ request1.User = "user1";
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
+ auto response1 = provider.CreateUser(request1);
+ UNIT_ASSERT(!response1.Error);
+
+ TLoginProvider::TLoginUserRequest request2;
+ request2 = MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY);
+ auto response2 = provider.LoginUser(request2);
+ UNIT_ASSERT_VALUES_EQUAL(response2.Error, "");
+
+ TLoginProvider::TValidateTokenRequest request3;
+ request3.Token = response2.Token;
+ auto response3 = provider.ValidateToken(request3);
+ UNIT_ASSERT_VALUES_EQUAL(response3.Error, "");
+ UNIT_ASSERT(response3.User == request1.User);
TPasswordComplexity passwordComplexity({
.MinLength = 8,
@@ -403,35 +371,18 @@ Y_UNIT_TEST_SUITE(Login) {
provider.UpdatePasswordCheckParameters(passwordComplexity);
- TLoginProvider::TModifyUserRequest modifyUser1RequestBad {
- .User = createUser1Request.User,
- .Password = "UserPassword1"
- };
-
- TLoginProvider::TBasicResponse modifyUser1ResponseBad = provider.ModifyUser(modifyUser1RequestBad);
- UNIT_ASSERT(!modifyUser1ResponseBad.Error.empty());
- UNIT_ASSERT_STRINGS_EQUAL(modifyUser1ResponseBad.Error, "Incorrect password format: should contain at least 2 number, should contain at least 2 special character");
-
- TLoginProvider::TModifyUserRequest modifyUser1Request {
- .User = createUser1Request.User,
- .Password = "paS*sw1oR#d7"
- };
-
- TLoginProvider::TBasicResponse modifyUser1Response = provider.ModifyUser(modifyUser1Request);
- UNIT_ASSERT_VALUES_EQUAL(modifyUser1Response.Error, "");
+ TLoginProvider::TModifyUserRequest request4;
+ request4.User = request1.User;
+ request4.Password = "UserPassword1";
+ auto response4 = provider.ModifyUser(request4);
+ UNIT_ASSERT(!response4.Error.empty());
+ UNIT_ASSERT_STRINGS_EQUAL(response4.Error, "Incorrect password format: should contain at least 2 number, should contain at least 2 special character");
- TLoginProvider::TLoginUserRequest loginUser1Request2 = {
- .User = modifyUser1Request.User,
- .Password = modifyUser1Request.Password.value()
- };
- TLoginProvider::TLoginUserResponse loginUser1Response2 = provider.LoginUser(loginUser1Request2);
- UNIT_ASSERT_VALUES_EQUAL(loginUser1Response2.Error, "");
- TLoginProvider::TValidateTokenRequest validateUser1TokenRequest2 = {
- .Token = loginUser1Response2.Token
- };
- TLoginProvider::TValidateTokenResponse validateUser1TokenResponse2 = provider.ValidateToken(validateUser1TokenRequest2);
- UNIT_ASSERT_VALUES_EQUAL(validateUser1TokenResponse2.Error, "");
- UNIT_ASSERT(validateUser1TokenResponse2.User == createUser1Request.User);
+ TLoginProvider::TModifyUserRequest request5;
+ request5.User = request1.User;
+ request5.Password = "paS*sw1oR#d7";
+ auto response5 = provider.ModifyUser(request5);
+ UNIT_ASSERT_VALUES_EQUAL(response5.Error, "");
}
Y_UNIT_TEST(TestGroups) {
@@ -588,7 +539,7 @@ Y_UNIT_TEST_SUITE(Login) {
provider.Audience = "test_audience1";
provider.RotateKeys();
{
- auto response1 = provider.CreateUser({.User = "user1", .Password = "password1"});
+ auto response1 = provider.CreateUser({.User = "user1", .HashedPassword = Base64Encode(PASSWORD1_HASHES)});
UNIT_ASSERT(!response1.Error);
}
{
@@ -600,7 +551,9 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT(!response1.Error);
}
{
- auto response1 = provider.LoginUser({.User = "user1", .Password = "password1", .Options = {.WithUserGroups = true}});
+ auto loginRequest = MakeScramPlainLoginRequest("user1", PASSWORD1_SCRAM_SERVER_KEY);
+ loginRequest.Options.WithUserGroups = true;
+ auto response1 = provider.LoginUser(loginRequest);
UNIT_ASSERT(!response1.Error);
auto response2 = provider.ValidateToken({.Token = response1.Token});
UNIT_ASSERT(!response2.Error);
@@ -616,7 +569,7 @@ Y_UNIT_TEST_SUITE(Login) {
provider.RotateKeys();
TLoginProvider::TCreateUserRequest request1;
request1.User = "user1";
- request1.Password = "password1";
+ request1.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto response1 = provider.CreateUser(request1);
UNIT_ASSERT(!response1.Error);
{
@@ -634,10 +587,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT(response3.ExternalAuth == request2.ExternalAuth);
}
{
- TLoginProvider::TLoginUserRequest request2;
- request2.User = request1.User;
- request2.Password = request1.Password;
- auto response2 = provider.LoginUser(request2);
+ auto response2 = provider.LoginUser(MakeScramPlainLoginRequest(request1.User, PASSWORD1_SCRAM_SERVER_KEY));
UNIT_ASSERT_VALUES_EQUAL(response2.Error, "");
TLoginProvider::TValidateTokenRequest request3;
request3.Token = response2.Token;
@@ -719,10 +669,9 @@ Y_UNIT_TEST_SUITE(Login) {
provider.Audience = "test_audience1";
provider.RotateKeys();
- TLoginProvider::TCreateUserRequest createUserRequest {
- .User = "user1",
- .Password = "password1"
- };
+ TLoginProvider::TCreateUserRequest createUserRequest;
+ createUserRequest.User = "user1";
+ createUserRequest.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto createUserResponse = provider.CreateUser(createUserRequest);
UNIT_ASSERT(!createUserResponse.Error);
@@ -731,7 +680,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = TStringBuilder() << "wrongpassword" << attempt});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, TStringBuilder() << "wronghash" << attempt));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -746,7 +695,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::RESET);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = TStringBuilder() << "wrongpassword" << accountLockoutInitializer.AttemptThreshold});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, TStringBuilder() << "wronghash" << accountLockoutInitializer.AttemptThreshold));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -755,7 +704,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = createUserRequest.Password});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, PASSWORD1_SCRAM_SERVER_KEY));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::SUCCESS);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "");
@@ -771,10 +720,9 @@ Y_UNIT_TEST_SUITE(Login) {
provider.Audience = "test_audience1";
provider.RotateKeys();
- TLoginProvider::TCreateUserRequest createUserRequest {
- .User = "user1",
- .Password = "password1"
- };
+ TLoginProvider::TCreateUserRequest createUserRequest;
+ createUserRequest.User = "user1";
+ createUserRequest.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto createUserResponse = provider.CreateUser(createUserRequest);
UNIT_ASSERT(!createUserResponse.Error);
@@ -783,7 +731,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = TStringBuilder() << "wrongpassword" << attempt});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, TStringBuilder() << "wronghash" << attempt));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -798,7 +746,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::RESET);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = "wrongpassword1"});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, "wronghash1"));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -808,7 +756,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = TStringBuilder() << "wrongpassword1" << attempt});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, TStringBuilder() << "wronghash1" << attempt));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -821,7 +769,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[createUserRequest.User]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = createUserRequest.User});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = createUserRequest.User, .Password = createUserRequest.Password});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(createUserRequest.User, PASSWORD1_SCRAM_SERVER_KEY));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::SUCCESS);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "");
@@ -838,13 +786,10 @@ Y_UNIT_TEST_SUITE(Login) {
provider.RotateKeys();
TString userName = "user1";
- TString userPassword = "password1";
-
- TLoginProvider::TCreateUserRequest createUserRequest {
- .User = userName,
- .Password = userPassword
- };
+ TLoginProvider::TCreateUserRequest createUserRequest;
+ createUserRequest.User = userName;
+ createUserRequest.HashedPassword = Base64Encode(PASSWORD1_HASHES);
auto createUserResponse = provider.CreateUser(createUserRequest);
UNIT_ASSERT(!createUserResponse.Error);
@@ -852,7 +797,7 @@ Y_UNIT_TEST_SUITE(Login) {
UNIT_ASSERT_VALUES_EQUAL(provider.IsLockedOut(provider.Sids[userName]), false);
auto checkLockoutResponse = provider.CheckLockOutUser({.User = userName});
UNIT_ASSERT_EQUAL(checkLockoutResponse.Status, TLoginProvider::TCheckLockOutResponse::EStatus::UNLOCKED);
- auto loginUserResponse = provider.LoginUser({.User = userName, .Password = TStringBuilder() << "wrongpassword" << attempt});
+ auto loginUserResponse = provider.LoginUser(MakeScramPlainLoginRequest(userName, TStringBuilder() << "wronghash" << attempt));
UNIT_ASSERT_EQUAL(loginUserResponse.Status, TLoginProvider::TLoginUserResponse::EStatus::INVALID_PASSWORD);
UNIT_ASSERT_VALUES_EQUAL(loginUserResponse.Error, "Invalid password");
}
@@ -879,221 +824,8 @@ Y_UNIT_TEST_SUITE(Login) {
}
}
- Y_UNIT_TEST(CreateAlterUserWithHashOldFormat) {
- TLoginProvider provider;
- provider.RotateKeys();
-
- {
- TString user = "user1";
- TString password = "password1";
- TString hash = R"(
- {
- "hash":"ZO37rNB37kP9hzmKRGfwc4aYrboDt4OBDsF1TBn5oLw=",
- "salt":"HTkpQjtVJgBoA0CZu+i3zg==",
- "type":"argon2id"
- }
- )";
-
- {
- TLoginProvider::TCreateUserRequest createRequest;
- createRequest.User = user;
- createRequest.Password = hash;
- createRequest.IsHashedPassword = true;
- auto createResponse = provider.CreateUser(createRequest);
- UNIT_ASSERT(!createResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest;
- loginRequest.User = user;
- loginRequest.Password = password;
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
- }
-
- {
- TString user = "user2";
- TString hash = R"(
- {
- "hash": "p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=",
- "salt": "Not in base64 format =) ",
- "type": "argon2id"
- }
- )";
-
- {
- TLoginProvider::TCreateUserRequest createRequest;
- createRequest.User = user;
- createRequest.Password = hash;
- createRequest.IsHashedPassword = true;
- auto createResponse = provider.CreateUser(createRequest);
- UNIT_ASSERT_STRING_CONTAINS(createResponse.Error, "Field \'salt\' must be in base64 format");
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest;
- loginRequest.User = user;
- loginRequest.Password = "somePassword";
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid user");
-
- auto sids = provider.Sids;
- UNIT_ASSERT(!sids.contains(user));
- }
- }
-
- {
- TString user = "user3";
- TString tempPassword = "password0";
- TString password = "password1";
- TString hash = R"(
- {
- "hash":"ZO37rNB37kP9hzmKRGfwc4aYrboDt4OBDsF1TBn5oLw=",
- "salt":"HTkpQjtVJgBoA0CZu+i3zg==",
- "type":"argon2id"
- }
- )";
-
- {
- TLoginProvider::TCreateUserRequest createRequest;
- createRequest.User = user;
- createRequest.Password = tempPassword;
- auto createResponse = provider.CreateUser(createRequest);
- UNIT_ASSERT(!createResponse.Error);
- }
-
- {
- TLoginProvider::TModifyUserRequest alterRequest;
- alterRequest.User = user;
- alterRequest.Password = hash;
- alterRequest.IsHashedPassword = true;
- auto alterResponse = provider.ModifyUser(alterRequest);
- UNIT_ASSERT(!alterResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest;
- loginRequest.User = user;
- loginRequest.Password = password;
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest;
- loginRequest.User = user;
- loginRequest.Password = tempPassword;
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid password");
- }
- }
- }
-
- Y_UNIT_TEST(CheckThatCacheDoesNotHoldOldPassword) {
- TLoginProvider provider(TPasswordComplexity(), TAccountLockout::TInitializer(), [] () {return true;}, {});
- provider.RotateKeys();
-
- {
- TLoginProvider::TCreateUserRequest createRequest {
- .User = "user1",
- .Password = "password1"
- };
- auto createResponse = provider.CreateUser(createRequest);
- UNIT_ASSERT(!createResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "password1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "pass1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid password");
- }
-
- // Try login with credentials from cache
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "password1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
-
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "pass1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid password");
- }
-
- // Change password for user1
- {
- TLoginProvider::TModifyUserRequest alterRequest {
- .User = "user1",
- .Password = "pass1"
- };
- auto alterResponse = provider.ModifyUser(alterRequest);
- UNIT_ASSERT(!alterResponse.Error);
- }
-
- // Cannot login with old password
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "password1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid password");
- }
-
- // Can login with new password
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "pass1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
-
- // Try login with credentials from cache
- // Cannot login with old password
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "password1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT_STRING_CONTAINS(loginResponse.Error, "Invalid password");
- }
-
- // Can login with new password
- {
- TLoginProvider::TLoginUserRequest loginRequest {
- .User = "user1",
- .Password = "pass1"
- };
- auto loginResponse = provider.LoginUser(loginRequest);
- UNIT_ASSERT(!loginResponse.Error);
- }
- }
-
Y_UNIT_TEST(NotIgnoreCheckErrors) {
- TLoginProvider provider(TPasswordComplexity(), TAccountLockout::TInitializer(), [] () {return true;}, {});
+ TLoginProvider provider{TPasswordComplexity(), TAccountLockout::TInitializer()};
provider.RotateKeys();
TLoginProvider::TPasswordCheckResult checkResult;
diff --git a/ydb/library/login/protos/login.proto b/ydb/library/login/protos/login.proto
index 1841008635b..84127d545cf 100644
--- a/ydb/library/login/protos/login.proto
+++ b/ydb/library/login/protos/login.proto
@@ -43,7 +43,7 @@ message THashInitParams {
message TSid {
string Name = 1;
ESidType.SidType Type = 2;
- string ArgonHash = 3 [deprecated = true];
+ reserved 3; reserved "ArgonHash";
repeated string Members = 4;
uint64 CreatedAt = 5; // microseconds
uint64 LastSuccessfulLogin = 6; // microseconds
diff --git a/ydb/library/login/ya.make b/ydb/library/login/ya.make
index bde0cdce0c0..32b0e8c26da 100644
--- a/ydb/library/login/ya.make
+++ b/ydb/library/login/ya.make
@@ -7,7 +7,6 @@ PEERDIR(
library/cpp/json
library/cpp/string_utils/base64
ydb/library/login/account_lockout
- ydb/library/login/cache
ydb/library/login/hashes_checker
ydb/library/login/protos
ydb/library/login/password_checker
@@ -27,7 +26,6 @@ RECURSE_FOR_TESTS(
RECURSE(
account_lockout
- cache
hashes_checker
password_checker
sasl