Skip to content

Commit 79e0fb7

Browse files
authored
Merge e09c6e1 into 2bc34d4
2 parents 2bc34d4 + e09c6e1 commit 79e0fb7

File tree

13 files changed

+713
-5
lines changed

13 files changed

+713
-5
lines changed

ydb/core/protos/auth.proto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ message TAuthConfig {
5656
optional string CertificateAuthenticationDomain = 80 [default = "cert"];
5757
optional bool EnableLoginAuthentication = 81 [default = true];
5858
optional string NodeRegistrationToken = 82 [default = "root@builtin", (Ydb.sensitive) = true];
59+
optional TPasswordCheckerParameters PasswordCheckerParameters = 83;
5960
}
6061

6162
message TUserRegistryConfig {
@@ -122,3 +123,13 @@ message TLdapAuthentication {
122123
optional string Scheme = 11 [default = "ldap"];
123124
optional TExtendedSettings ExtendedSettings = 12;
124125
}
126+
127+
message TPasswordCheckerParameters {
128+
optional uint32 MinimumLength = 1 [default = 0];
129+
optional uint32 MaximumLength = 2 [default = 4294967295];
130+
optional bool RestrictLower = 3;
131+
optional bool RestrictUpper = 4;
132+
optional bool RestrictNumbers = 5;
133+
optional bool RestrictSpecial = 6;
134+
optional string SpecialChars = 7 [default = "!@#$%^&*()_+{}|<>?="];
135+
}

ydb/core/tx/schemeshard/schemeshard_impl.cpp

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
#include <ydb/core/base/appdata.h>
1212
#include <ydb/core/base/tx_processing.h>
1313
#include <ydb/core/protos/feature_flags.pb.h>
14+
#include <ydb/core/protos/auth.pb.h>
1415
#include <ydb/core/engine/mkql_proto.h>
1516
#include <ydb/core/sys_view/partition_stats/partition_stats.h>
1617
#include <ydb/core/statistics/events.h>
1718
#include <ydb/core/statistics/service/service.h>
1819
#include <ydb/core/scheme/scheme_types_proto.h>
1920
#include <ydb/core/tx/columnshard/bg_tasks/events/events.h>
2021
#include <ydb/core/tx/scheme_board/events_schemeshard.h>
22+
#include <ydb/library/login/password_checker/password_checker.h>
2123
#include <yql/essentials/minikql/mkql_type_ops.h>
2224
#include <yql/essentials/providers/common/proto/gateways_config.pb.h>
2325
#include <util/random/random.h>
@@ -4432,6 +4434,16 @@ TSchemeShard::TSchemeShard(const TActorId &tablet, TTabletStorageInfo *info)
44324434
COUNTER_PQ_STATS_WRITTEN,
44334435
COUNTER_PQ_STATS_BATCH_LATENCY)
44344436
, AllowDataColumnForIndexTable(0, 0, 1)
4437+
, PasswordCheckParameters({
4438+
.MinPasswordLength = AppData()->AuthConfig.GetPasswordCheckerParameters().GetMinimumLength(),
4439+
.MaxPasswordLength = AppData()->AuthConfig.GetPasswordCheckerParameters().GetMaximumLength(),
4440+
.NeedLowerCase = AppData()->AuthConfig.GetPasswordCheckerParameters().GetRestrictLower(),
4441+
.NeedUpperCase = AppData()->AuthConfig.GetPasswordCheckerParameters().GetRestrictUpper(),
4442+
.NeedNumbers = AppData()->AuthConfig.GetPasswordCheckerParameters().GetRestrictNumbers(),
4443+
.NeedSpecialSymbols = AppData()->AuthConfig.GetPasswordCheckerParameters().GetRestrictSpecial(),
4444+
.SpecialSymbols = AppData()->AuthConfig.GetPasswordCheckerParameters().GetSpecialChars()
4445+
})
4446+
, LoginProvider(PasswordCheckParameters)
44354447
{
44364448
TabletCountersPtr.Reset(new TProtobufTabletCounters<
44374449
ESimpleCounters_descriptor,
@@ -7117,6 +7129,10 @@ void TSchemeShard::ApplyConsoleConfigs(const NKikimrConfig::TAppConfig& appConfi
71177129
);
71187130
}
71197131

7132+
if (appConfig.HasAuthConfig()) {
7133+
ConfigureLoginProvider(appConfig.GetAuthConfig(), ctx);
7134+
}
7135+
71207136
if (IsSchemeShardConfigured()) {
71217137
StartStopCompactionQueues();
71227138
if (BackgroundCleaningQueue) {
@@ -7310,6 +7326,35 @@ void TSchemeShard::ConfigureBackgroundCleaningQueue(
73107326
<< ", InflightLimit# " << cleaningConfig.InflightLimit);
73117327
}
73127328

7329+
void TSchemeShard::ConfigureLoginProvider(
7330+
const ::NKikimrProto::TAuthConfig& config,
7331+
const TActorContext &ctx)
7332+
{
7333+
const auto& passwordCheckParameters = config.GetPasswordCheckerParameters();
7334+
PasswordCheckParameters.SetMinPasswordLength(passwordCheckParameters.GetMinimumLength());
7335+
PasswordCheckParameters.SetMaxPasswordLength(passwordCheckParameters.GetMaximumLength());
7336+
PasswordCheckParameters.SetLowerCaseUse(passwordCheckParameters.GetRestrictLower());
7337+
PasswordCheckParameters.SetUpperCaseUse(passwordCheckParameters.GetRestrictUpper());
7338+
PasswordCheckParameters.SetNumbersUse(passwordCheckParameters.GetRestrictNumbers());
7339+
PasswordCheckParameters.SetSpecialSymbolsUse(passwordCheckParameters.GetRestrictSpecial());
7340+
PasswordCheckParameters.SetSpecialSymbols(passwordCheckParameters.GetSpecialChars());
7341+
7342+
LoginProvider.UpdatePasswordCheckParameters(PasswordCheckParameters);
7343+
7344+
auto printBool = [] (bool flag) -> TString {
7345+
return (flag ? "true" : "false");
7346+
};
7347+
7348+
LOG_NOTICE_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
7349+
"LoginProvider configured: MinPasswordLength# " << PasswordCheckParameters.GetMinPasswordLength()
7350+
<< ", MaxPasswordLength# " << PasswordCheckParameters.GetMaxPasswordLength()
7351+
<< ", NeedLowerCase# " << printBool(PasswordCheckParameters.NeedLowerCaseUse())
7352+
<< ", NeedUpperCase# " << printBool(PasswordCheckParameters.NeedUpperCaseUse())
7353+
<< ", NeedNumbers# " << printBool(PasswordCheckParameters.NeedNumbersUse())
7354+
<< ", NeedSpecialSymbols# " << printBool(PasswordCheckParameters.NeedSpecialSymbolsUse())
7355+
<< ", SpecialSymbols# " << passwordCheckParameters.GetSpecialChars());
7356+
}
7357+
73137358
void TSchemeShard::StartStopCompactionQueues() {
73147359
// note, that we don't need to check current state of compaction queue
73157360
if (IsServerlessDomain(TPath::Init(RootPathId(), this))) {
@@ -7477,19 +7522,19 @@ void TSchemeShard::ResolveSA() {
74777522
StatisticsAggregatorId = subDomainInfo->GetTenantStatisticsAggregatorID();
74787523
LOG_DEBUG_S(TlsActivationContext->AsActorContext(), NKikimrServices::STATISTICS,
74797524
"ResolveSA(), StatisticsAggregatorId=" << StatisticsAggregatorId
7480-
<< ", at schemeshard: " << TabletID());
7525+
<< ", at schemeshard: " << TabletID());
74817526
ConnectToSA();
74827527
}
74837528
}
74847529

74857530
void TSchemeShard::ConnectToSA() {
74867531
if (!EnableStatistics)
74877532
return;
7488-
7533+
74897534
if (!StatisticsAggregatorId) {
74907535
LOG_DEBUG_S(TlsActivationContext->AsActorContext(), NKikimrServices::STATISTICS,
74917536
"ConnectToSA(), no StatisticsAggregatorId"
7492-
<< ", at schemeshard: " << TabletID());
7537+
<< ", at schemeshard: " << TabletID());
74937538
return;
74947539
}
74957540
auto policy = NTabletPipe::TClientRetryPolicy::WithRetries();
@@ -7606,8 +7651,8 @@ TDuration TSchemeShard::SendBaseStatsToSA() {
76067651
<< ", path count: " << count
76077652
<< ", at schemeshard: " << TabletID());
76087653

7609-
return TDuration::Seconds(SendStatsIntervalMinSeconds
7610-
+ RandomNumber<ui64>(SendStatsIntervalMaxSeconds - SendStatsIntervalMinSeconds));
7654+
return TDuration::Seconds(SendStatsIntervalMinSeconds
7655+
+ RandomNumber<ui64>(SendStatsIntervalMaxSeconds - SendStatsIntervalMinSeconds));
76117656
}
76127657

76137658
} // namespace NSchemeShard

ydb/core/tx/schemeshard/schemeshard_impl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include <ydb/core/blob_depot/events.h>
6565

6666
#include <ydb/library/login/login.h>
67+
#include <ydb/library/login/password_checker/password_checker.h>
6768

6869
#include <util/generic/ptr.h>
6970

@@ -496,6 +497,10 @@ class TSchemeShard
496497
const NKikimrConfig::TBackgroundCleaningConfig& config,
497498
const TActorContext &ctx);
498499

500+
void ConfigureLoginProvider(
501+
const ::NKikimrProto::TAuthConfig& config,
502+
const TActorContext &ctx);
503+
499504
void StartStopCompactionQueues();
500505

501506
void WaitForTableProfiles(ui64 importId, ui32 itemIdx);
@@ -1455,6 +1460,7 @@ class TSchemeShard
14551460
void ChangeDiskSpaceSoftQuotaBytes(i64 delta) override;
14561461
void AddDiskSpaceSoftQuotaBytes(EUserFacingStorageType storageType, ui64 addend) override;
14571462

1463+
NLogin::TPasswordCheckParameters PasswordCheckParameters;
14581464
NLogin::TLoginProvider LoginProvider;
14591465

14601466
private:

ydb/core/tx/schemeshard/ut_login/ut_login.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <util/string/join.h>
22

33
#include <ydb/library/login/login.h>
4+
#include <ydb/library/login/password_checker/password_checker.h>
45
#include <ydb/library/actors/http/http_proxy.h>
56
#include <ydb/library/testlib/service_mocks/ldap_mock/ldap_simple_server.h>
67
#include <ydb/core/tx/schemeshard/ut_helpers/helpers.h>
@@ -27,6 +28,23 @@ void TestCreateAlterLoginCreateUser(TTestActorRuntime& runtime, ui64 txId, const
2728
TestModificationResults(runtime, txId, expectedResults);
2829
}
2930

31+
void SetPasswordCheckerParameters(TTestActorRuntime &runtime, ui64 schemeShard, const NLogin::TPasswordCheckParameters::TInitializer& parameters) {
32+
auto request = MakeHolder<NConsole::TEvConsole::TEvConfigNotificationRequest>();
33+
34+
::NKikimrProto::TPasswordCheckerParameters passwordCheckParameters;
35+
passwordCheckParameters.SetMinimumLength(parameters.MinPasswordLength);
36+
passwordCheckParameters.SetMaximumLength(parameters.MaxPasswordLength);
37+
passwordCheckParameters.SetRestrictLower(parameters.NeedLowerCase);
38+
passwordCheckParameters.SetRestrictUpper(parameters.NeedUpperCase);
39+
passwordCheckParameters.SetRestrictNumbers(parameters.NeedNumbers);
40+
passwordCheckParameters.SetRestrictSpecial(parameters.NeedSpecialSymbols);
41+
passwordCheckParameters.SetSpecialChars(parameters.SpecialSymbols);
42+
*request->Record.MutableConfig()->MutableAuthConfig()->MutablePasswordCheckerParameters() = passwordCheckParameters;
43+
SetConfig(runtime, schemeShard, std::move(request));
44+
}
45+
46+
const TString VALID_SPECIAL_SYMBOLS = "!@#$%^&*()_+{}|<>?=";
47+
3048
} // namespace NSchemeShardUT_Private
3149

3250
Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
@@ -66,6 +84,128 @@ Y_UNIT_TEST_SUITE(TSchemeShardLoginTest) {
6684
UNIT_ASSERT(describe.GetPathDescription().GetDomainDescription().HasSecurityState());
6785
UNIT_ASSERT(describe.GetPathDescription().GetDomainDescription().GetSecurityState().PublicKeysSize() > 0);
6886
}
87+
88+
Y_UNIT_TEST(ChangeAcceptablePasswordParameters) {
89+
TTestBasicRuntime runtime;
90+
TTestEnv env(runtime);
91+
ui64 txId = 100;
92+
// Password parameters:
93+
// length 0 - 4294967295
94+
// optional: lower case, upper case, numbers, special symbols from list !@#$%^&*()_+{}|<>?=
95+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user1", "password1", {{NKikimrScheme::StatusSuccess}});
96+
auto resultLogin = Login(runtime, "user1", "password1");
97+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
98+
auto describe = DescribePath(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
99+
UNIT_ASSERT(describe.HasPathDescription());
100+
UNIT_ASSERT(describe.GetPathDescription().HasDomainDescription());
101+
UNIT_ASSERT(describe.GetPathDescription().GetDomainDescription().HasSecurityState());
102+
UNIT_ASSERT(describe.GetPathDescription().GetDomainDescription().GetSecurityState().PublicKeysSize() > 0);
103+
104+
// Accept password without lower case symbols
105+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user2", "PASSWORDU2", {{NKikimrScheme::StatusSuccess}});
106+
resultLogin = Login(runtime, "user2", "PASSWORDU2");
107+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
108+
// Password parameters:
109+
// length 0 - 4294967295
110+
// optional: upper case, numbers, special symbols from list !@#$%^&*()_+{}|<>?=
111+
// required: lower case
112+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.NeedLowerCase = true, .SpecialSymbols = VALID_SPECIAL_SYMBOLS});
113+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user3", "PASSWORDU3", {{NKikimrScheme::StatusPreconditionFailed}});
114+
// Add lower case symbols to password
115+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user3", "PASswORDu3", {{NKikimrScheme::StatusSuccess}});
116+
resultLogin = Login(runtime, "user3", "PASswORDu3");
117+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
118+
119+
// Accept password without upper case symbols
120+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user4", "passwordu4", {{NKikimrScheme::StatusSuccess}});
121+
resultLogin = Login(runtime, "user4", "passwordu4");
122+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
123+
// Password parameters:
124+
// length 0 - 4294967295
125+
// optional: numbers, special symbols from list !@#$%^&*()_+{}|<>?=
126+
// required: lower case, upper case
127+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.NeedLowerCase = true, .NeedUpperCase = true, .SpecialSymbols = VALID_SPECIAL_SYMBOLS});
128+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user5", "passwordu5", {{NKikimrScheme::StatusPreconditionFailed}});
129+
// Add upper case symbols to password
130+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user5", "PASswORDu5", {{NKikimrScheme::StatusSuccess}});
131+
resultLogin = Login(runtime, "user5", "PASswORDu5");
132+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
133+
134+
// Accept short and long passwords
135+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user6", "pasSWu6", {{NKikimrScheme::StatusSuccess}});
136+
resultLogin = Login(runtime, "user6", "pasSWu6");
137+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
138+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user7", "pasSW12345Word!*&u7", {{NKikimrScheme::StatusSuccess}});
139+
resultLogin = Login(runtime, "user7", "pasSW12345Word!*&u7");
140+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
141+
// Password parameters:
142+
// length 8 - 15
143+
// optional: numbers, special symbols from list !@#$%^&*()_+{}|<>?=
144+
// required: lower case, upper case
145+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.MinPasswordLength = 8, .MaxPasswordLength = 15, .NeedLowerCase = true, .NeedUpperCase = true, .SpecialSymbols = VALID_SPECIAL_SYMBOLS});
146+
// Too short password
147+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user8", "pasSWu8", {{NKikimrScheme::StatusPreconditionFailed}});
148+
// Too long password
149+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user8", "pasSW12345Word!*&u8", {{NKikimrScheme::StatusPreconditionFailed}});
150+
// Password has correct length
151+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user8", "PASswORDu8", {{NKikimrScheme::StatusSuccess}});
152+
resultLogin = Login(runtime, "user8", "PASswORDu8");
153+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
154+
155+
// Accept password without numbers
156+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user9", "passWorDunine", {{NKikimrScheme::StatusSuccess}});
157+
resultLogin = Login(runtime, "user9", "passWorDunine");
158+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
159+
// Password parameters:
160+
// length 8 - 15
161+
// optional: special symbols from list !@#$%^&*()_+{}|<>?=
162+
// required: lower case, upper case, numbers
163+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.MinPasswordLength = 8,
164+
.MaxPasswordLength = 15,
165+
.NeedLowerCase = true,
166+
.NeedUpperCase = true,
167+
.NeedNumbers = true,
168+
.SpecialSymbols = VALID_SPECIAL_SYMBOLS});
169+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user10", "passWorDuten", {{NKikimrScheme::StatusPreconditionFailed}});
170+
// Password with numbers
171+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user10", "PASswORDu10", {{NKikimrScheme::StatusSuccess}});
172+
resultLogin = Login(runtime, "user10", "PASswORDu10");
173+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
174+
175+
// Accept password without special symbols
176+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user11", "passWorDu11", {{NKikimrScheme::StatusSuccess}});
177+
resultLogin = Login(runtime, "user11", "passWorDu11");
178+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
179+
// Password parameters:
180+
// length 8 - 15
181+
// required: lower case, upper case, numbers, special symbols from list !@#$%^&*()_+{}|<>?=
182+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.MinPasswordLength = 8,
183+
.MaxPasswordLength = 15,
184+
.NeedLowerCase = true,
185+
.NeedUpperCase = true,
186+
.NeedNumbers = true,
187+
.NeedSpecialSymbols = true,
188+
.SpecialSymbols = VALID_SPECIAL_SYMBOLS});
189+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user12", "passWorDu12", {{NKikimrScheme::StatusPreconditionFailed}});
190+
// Password with special symbols
191+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user12", "PASswORDu12*&%#", {{NKikimrScheme::StatusSuccess}});
192+
resultLogin = Login(runtime, "user12", "PASswORDu12*&%#");
193+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
194+
// Password parameters:
195+
// length 8 - 15
196+
// required: lower case, upper case, numbers, special symbols from list *#
197+
SetPasswordCheckerParameters(runtime, TTestTxConfig::SchemeShard, {.MinPasswordLength = 8,
198+
.MaxPasswordLength = 15,
199+
.NeedLowerCase = true,
200+
.NeedUpperCase = true,
201+
.NeedNumbers = true,
202+
.NeedSpecialSymbols = true,
203+
.SpecialSymbols = "*#"}); // Only 2 special symbols are valid
204+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user13", "PASswORDu13*&%#", {{NKikimrScheme::StatusPreconditionFailed}});
205+
TestCreateAlterLoginCreateUser(runtime, ++txId, "/MyRoot", "user13", "PASswORDu12*#", {{NKikimrScheme::StatusSuccess}});
206+
resultLogin = Login(runtime, "user13", "PASswORDu12*#");
207+
UNIT_ASSERT_VALUES_EQUAL(resultLogin.error(), "");
208+
}
69209
}
70210

71211
namespace NSchemeShardUT_Private {

0 commit comments

Comments
 (0)