Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions ydb/core/sys_view/ut_auth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,33 @@ Y_UNIT_TEST_SUITE(AuthSystemView) {


{
auto loginResult = env.GetClient().Login(*(env.GetServer().GetRuntime()), "user1", "password1");
UNIT_ASSERT_EQUAL(loginResult.GetError(), "");
// login operation occurs implicitly when driver is created
// but to check whether a login attempt was successful we need to execute a simple query
auto driverConfig = TDriverConfig()
.SetEndpoint(env.GetEndpoint())
.SetDatabase("/Root")
.SetCredentialsProviderFactory(NYdb::CreateLoginCredentialsProviderFactory({
.User = "user1",
.Password = "password1",
}));
auto driver = TDriver(driverConfig);

NQuery::TQueryClient client(driver);
auto result = client.ExecuteQuery("SELECT 1;", NQuery::TTxControl::NoTx()).GetValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}

{
// login operation occurs implicitly when driver is created
for (size_t i = 0; i < 4; i++) {
auto loginResult = env.GetClient().Login(*(env.GetServer().GetRuntime()), "user1", "wrongPassword");
UNIT_ASSERT_EQUAL(loginResult.GetError(), "Invalid password");
auto driverConfig = TDriverConfig()
.SetEndpoint(env.GetEndpoint())
.SetDatabase("/Root")
.SetCredentialsProviderFactory(NYdb::CreateLoginCredentialsProviderFactory({
.User = "user1",
.Password = "wrongPassword",
}));
auto driver = TDriver(driverConfig);
}
}

Expand All @@ -205,8 +224,21 @@ Y_UNIT_TEST_SUITE(AuthSystemView) {

// Check that user is locked out and cannot login
{
auto loginResult = env.GetClient().Login(*(env.GetServer().GetRuntime()), "user1", "password1");
UNIT_ASSERT_EQUAL(loginResult.GetError(), "User user1 login denied: too many failed password attempts");
// login operation occurs implicitly when driver is created
// but to check whether a login attempt was successful we need to execute a simple query
auto driverConfig = TDriverConfig()
.SetEndpoint(env.GetEndpoint())
.SetDatabase("/Root")
.SetCredentialsProviderFactory(NYdb::CreateLoginCredentialsProviderFactory({
.User = "user1",
.Password = "password1",
}));
auto driver = TDriver(driverConfig);

NQuery::TQueryClient client(driver);
auto result = client.ExecuteQuery("SELECT 1;", NQuery::TTxControl::NoTx()).GetValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::CLIENT_UNAUTHENTICATED, result.GetIssues().ToString());
UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "User user1 login denied: too many failed password attempts");
}

Sleep(TDuration::Seconds(5));
Expand All @@ -227,8 +259,20 @@ Y_UNIT_TEST_SUITE(AuthSystemView) {

// User can login
{
auto loginResult = env.GetClient().Login(*(env.GetServer().GetRuntime()), "user1", "password1");
UNIT_ASSERT_EQUAL(loginResult.GetError(), "");
// login operation occurs implicitly when driver is created
// but to check whether a login attempt was successful we need to execute a simple query
auto driverConfig = TDriverConfig()
.SetEndpoint(env.GetEndpoint())
.SetDatabase("/Root")
.SetCredentialsProviderFactory(NYdb::CreateLoginCredentialsProviderFactory({
.User = "user1",
.Password = "password1",
}));
auto driver = TDriver(driverConfig);

NQuery::TQueryClient client(driver);
auto result = client.ExecuteQuery("SELECT 1;", NQuery::TTxControl::NoTx()).GetValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}

// Check that FailedAttemptCount is reset
Expand Down
75 changes: 75 additions & 0 deletions ydb/services/ydb/ydb_login_ut.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <format>

#include <library/cpp/string_utils/base64/base64.h>
#include <library/cpp/testing/unittest/tests_data.h>
#include <library/cpp/testing/unittest/registar.h>

Expand Down Expand Up @@ -151,6 +152,41 @@ Y_UNIT_TEST_SUITE(TGRpcAuthentication) {
loginConnection.Stop();
}

Y_UNIT_TEST(ValidHashCredentials) {
TLoginClientConnection loginConnection;

std::string hash = R"(
{
"version": 1,
"argon2id": "HTkpQjtVJgBoA0CZu+i3zg==$ZO37rNB37kP9hzmKRGfwc4aYrboDt4OBDsF1TBn5oLw=",
"scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
}
)";
auto createUserQuery = std::format("CREATE USER {0:} HASH '{1:}'", std::string(User), std::string(Base64Encode(hash)));
auto result = loginConnection.ExecuteSql("root@builtin", TString(createUserQuery));
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());

auto factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = "password1"});
auto loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_NO_EXCEPTION(loginProvider->GetAuthInfo());

hash = R"(
{
"version": 1,
"argon2id": "HTkpQjtVJgBoA0CZu+i3zg==$ZO37rNB37kP9hzmKRGfwc4aYrboDt4OBDsF1TBn5oLw="
}
)";
auto alterUserQuery = std::format("ALTER USER {0:} HASH '{1:}'", std::string(User), std::string(Base64Encode(hash)));
result = loginConnection.ExecuteSql("root@builtin", TString(alterUserQuery));
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());

factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = "password1"});
loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_NO_EXCEPTION(loginProvider->GetAuthInfo());

loginConnection.Stop();
}

Y_UNIT_TEST(InvalidPassword) {
TLoginClientConnection loginConnection;
loginConnection.CreateUser(User, Password);
Expand All @@ -159,6 +195,45 @@ Y_UNIT_TEST_SUITE(TGRpcAuthentication) {
auto loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_EXCEPTION_CONTAINS(loginProvider->GetAuthInfo(), yexception, "Invalid password");

std::string hash = R"(
{
"version": 1,
"argon2id": "HTkpQjtVJgBoA0CZu+i3zg==$ZO37rNB37kP9hzmKRGfwc4aYrboDt4OBDsF1TBn5oLw=",
"scram-sha-256": "4096:s0QSrrFVkMTh3k2TTk860A==$LmCubRpIYV1zHMLucTtu7XjhB+PgWwH8ABCYGyVF1mo=:eUrie0C98tEFgygSOtom/fwPmgnMxeq53l7YTFfYncc="
}
)";
auto alterUserQuery = std::format("ALTER USER {0:} HASH '{1:}'", std::string(User), std::string(Base64Encode(hash)));
auto result = loginConnection.ExecuteSql("root@builtin", TString(alterUserQuery));
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());

factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = Password});
loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_EXCEPTION_CONTAINS(loginProvider->GetAuthInfo(), yexception, "Invalid password");

loginConnection.Stop();
}

Y_UNIT_TEST(UnknownUser) {
TLoginClientConnection loginConnection;

auto factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = Password});
auto loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_EXCEPTION_CONTAINS(loginProvider->GetAuthInfo(), yexception, "Cannot find user: user");

loginConnection.CreateUser(User, Password);

factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = Password});
loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_NO_EXCEPTION(loginProvider->GetAuthInfo());

auto dropUserQuery = std::format("DROP USER {0:}", std::string(User));
auto result = loginConnection.ExecuteSql("root@builtin", TString(dropUserQuery));
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());

factory = CreateLoginCredentialsProviderFactory({.User = User, .Password = Password});
loginProvider = factory->CreateProvider(loginConnection.GetCoreFacility());
UNIT_ASSERT_EXCEPTION_CONTAINS(loginProvider->GetAuthInfo(), yexception, "Cannot find user: user");

loginConnection.Stop();
}

Expand Down
Loading