From e9186e3b66a8e84b23705960496786260a8041d0 Mon Sep 17 00:00:00 2001 From: Andrei Molotkov Date: Thu, 27 Feb 2025 16:01:30 +0000 Subject: [PATCH 1/2] Check account lockout config --- .../validation/auth_config_validator.cpp | 28 ++++++-- .../auth_config_validator_ut.cpp | 67 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/ydb/core/config/validation/auth_config_validator.cpp b/ydb/core/config/validation/auth_config_validator.cpp index 7f558b37a66e..964bbce5b96a 100644 --- a/ydb/core/config/validation/auth_config_validator.cpp +++ b/ydb/core/config/validation/auth_config_validator.cpp @@ -1,13 +1,14 @@ #include #include #include +#include #include "validators.h" namespace NKikimr::NConfig { namespace { -EValidationResult ValidatePasswordComplexity(const NKikimrProto::TPasswordComplexity& passwordComplexity, std::vector&msg) { +EValidationResult ValidatePasswordComplexity(const NKikimrProto::TPasswordComplexity& passwordComplexity, std::vector& msg) { size_t minCountOfRequiredChars = passwordComplexity.GetMinLowerCaseCount() + passwordComplexity.GetMinUpperCaseCount() + passwordComplexity.GetMinNumbersCount() + @@ -20,13 +21,32 @@ EValidationResult ValidatePasswordComplexity(const NKikimrProto::TPasswordComple return EValidationResult::Ok; } +EValidationResult ValidateAccountLockout(const NKikimrProto::TAccountLockout& accountLockout, std::vector& msg) { + TDuration attemptResetDuration; + if (TDuration::TryParse(accountLockout.GetAttemptResetDuration(), attemptResetDuration)) { + return EValidationResult::Ok; + } + msg = std::vector{"account_lockout: Cannot parse attempt reset duration"}; + return EValidationResult::Error; +} + } // namespace EValidationResult ValidateAuthConfig(const NKikimrProto::TAuthConfig& authConfig, std::vector& msg) { - EValidationResult validatePasswordComplexityResult = ValidatePasswordComplexity(authConfig.GetPasswordComplexity(), msg); - if (validatePasswordComplexityResult == EValidationResult::Error) { - return EValidationResult::Error; + if (authConfig.HasPasswordComplexity()) { + EValidationResult validateResult = ValidatePasswordComplexity(authConfig.GetPasswordComplexity(), msg); + if (validateResult == EValidationResult::Error) { + return EValidationResult::Error; + } } + + if (authConfig.HasAccountLockout()) { + EValidationResult validateResult = ValidateAccountLockout(authConfig.GetAccountLockout(), msg); + if (validateResult == EValidationResult::Error) { + return EValidationResult::Error; + } + } + if (msg.size() > 0) { return EValidationResult::Warn; } diff --git a/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp b/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp index 8b68f4027aad..bf5b108e63dd 100644 --- a/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp +++ b/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp @@ -40,4 +40,71 @@ Y_UNIT_TEST_SUITE(AuthConfigValidation) { UNIT_ASSERT_STRINGS_EQUAL(error.front(), "password_complexity: Min length of password cannot be less than " "total min counts of lower case chars, upper case chars, numbers and special chars"); } + + Y_UNIT_TEST(AcceptValidAccountLockoutConfig) { + NKikimrProto::TAuthConfig authConfig; + NKikimrProto::TAccountLockout* validAccountLockoutConfig = authConfig.MutableAccountLockout(); + + { + validAccountLockoutConfig->SetAttemptResetDuration("12h"); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); + UNIT_ASSERT_C(error.empty(), "Should not be errors"); + } + + { + validAccountLockoutConfig->SetAttemptResetDuration("5m"); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); + UNIT_ASSERT_C(error.empty(), "Should not be errors"); + } + + { + validAccountLockoutConfig->SetAttemptResetDuration("5s"); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); + UNIT_ASSERT_C(error.empty(), "Should not be errors"); + } + } + + Y_UNIT_TEST(CannotAcceptInvalidAccountLockoutConfig) { + NKikimrProto::TAuthConfig authConfig; + NKikimrProto::TAccountLockout* invalidAccountLockoutConfig = authConfig.MutableAccountLockout(); + + { + invalidAccountLockoutConfig->SetAttemptResetDuration("h"); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Error); + UNIT_ASSERT_VALUES_EQUAL(error.size(), 1); + UNIT_ASSERT_STRINGS_EQUAL(error.front(), "account_lockout: Cannot parse attempt reset duration"); + } + + { + invalidAccountLockoutConfig->SetAttemptResetDuration(""); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Error); + UNIT_ASSERT_VALUES_EQUAL(error.size(), 1); + UNIT_ASSERT_STRINGS_EQUAL(error.front(), "account_lockout: Cannot parse attempt reset duration"); + } + + { + invalidAccountLockoutConfig->SetAttemptResetDuration("12hhh"); + + std::vector error; + EValidationResult result = ValidateAuthConfig(authConfig, error); + UNIT_ASSERT_EQUAL(result, EValidationResult::Error); + UNIT_ASSERT_VALUES_EQUAL(error.size(), 1); + UNIT_ASSERT_STRINGS_EQUAL(error.front(), "account_lockout: Cannot parse attempt reset duration"); + } + } } From 56c805e2977cc07a16ac0dbffe3a29dd7102d30a Mon Sep 17 00:00:00 2001 From: Andrei Molotkov Date: Thu, 27 Feb 2025 16:31:28 +0000 Subject: [PATCH 2/2] Apply comments --- .../auth_config_validator_ut/auth_config_validator_ut.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp b/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp index bf5b108e63dd..b8333656ea9b 100644 --- a/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp +++ b/ydb/core/config/validation/auth_config_validator_ut/auth_config_validator_ut.cpp @@ -19,7 +19,7 @@ Y_UNIT_TEST_SUITE(AuthConfigValidation) { std::vector error; EValidationResult result = ValidateAuthConfig(authConfig, error); UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); - UNIT_ASSERT_C(error.empty(), "Should not be errors"); + UNIT_ASSERT_C(error.empty(), error.front()); } Y_UNIT_TEST(CannotAcceptInvalidPasswordComplexity) { @@ -51,7 +51,7 @@ Y_UNIT_TEST_SUITE(AuthConfigValidation) { std::vector error; EValidationResult result = ValidateAuthConfig(authConfig, error); UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); - UNIT_ASSERT_C(error.empty(), "Should not be errors"); + UNIT_ASSERT_C(error.empty(), error.front()); } { @@ -60,7 +60,7 @@ Y_UNIT_TEST_SUITE(AuthConfigValidation) { std::vector error; EValidationResult result = ValidateAuthConfig(authConfig, error); UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); - UNIT_ASSERT_C(error.empty(), "Should not be errors"); + UNIT_ASSERT_C(error.empty(), error.front()); } { @@ -69,7 +69,7 @@ Y_UNIT_TEST_SUITE(AuthConfigValidation) { std::vector error; EValidationResult result = ValidateAuthConfig(authConfig, error); UNIT_ASSERT_EQUAL(result, EValidationResult::Ok); - UNIT_ASSERT_C(error.empty(), "Should not be errors"); + UNIT_ASSERT_C(error.empty(), error.front()); } }