aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Efimov <xeno@prnwatch.com>2022-02-21 17:00:04 +0300
committerAlexey Efimov <xeno@prnwatch.com>2022-02-21 17:00:04 +0300
commit7b18d121542023f9a06c68d4265932d0d97b7586 (patch)
treea3a5c1d01f6ed9144cdb987018416182b5921a2c
parent1f48d5a86f33a9f0f7364814271914f71b48d965 (diff)
downloadydb-7b18d121542023f9a06c68d4265932d0d97b7586.tar.gz
initialize root domain with default user, groups and access rights KIKIMR-14361
ref:6beb48d94021d272c7da87fef709fcbc2aec8046
-rw-r--r--ydb/core/base/appdata.h1
-rw-r--r--ydb/core/driver_lib/run/run.cpp2
-rw-r--r--ydb/core/mind/hive/monitoring.cpp3
-rw-r--r--ydb/core/protos/config.proto15
-rw-r--r--ydb/core/testlib/test_client.cpp1
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__init.cpp2
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__init_root.cpp90
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp13
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.cpp5
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.h4
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_path.cpp8
-rw-r--r--ydb/library/aclib/aclib.cpp10
-rw-r--r--ydb/library/login/login.cpp2
-rw-r--r--ydb/library/login/login.h5
-rw-r--r--ydb/library/yaml_config/yaml_config_parser.cpp98
-rw-r--r--ydb/tests/functional/ydb_cli/ya.make1
16 files changed, 234 insertions, 26 deletions
diff --git a/ydb/core/base/appdata.h b/ydb/core/base/appdata.h
index c666f7468c0..2dae5a954b0 100644
--- a/ydb/core/base/appdata.h
+++ b/ydb/core/base/appdata.h
@@ -146,6 +146,7 @@ struct TAppData {
NKikimrConfig::TDataShardConfig DataShardConfig;
NKikimrConfig::TMeteringConfig MeteringConfig;
NKikimrConfig::TCompactionConfig CompactionConfig;
+ NKikimrConfig::TDomainsConfig DomainsConfig;
bool EnforceUserTokenRequirement = false;
bool AllowHugeKeyValueDeletes = true; // delete when all clients limit deletes per request
bool EnableKqpSpilling = false;
diff --git a/ydb/core/driver_lib/run/run.cpp b/ydb/core/driver_lib/run/run.cpp
index 1d735aa67da..039553e4cac 100644
--- a/ydb/core/driver_lib/run/run.cpp
+++ b/ydb/core/driver_lib/run/run.cpp
@@ -138,6 +138,7 @@ public:
virtual void Initialize(NKikimr::TAppData* appData) override
{
+ appData->DomainsConfig = Config.GetDomainsConfig();
// setup domain info
appData->DomainsInfo = new TDomainsInfo();
for (const NKikimrConfig::TDomainsConfig::TDomain &domain : Config.GetDomainsConfig().GetDomain()) {
@@ -189,7 +190,6 @@ public:
}
const auto& securityConfig(Config.GetDomainsConfig().GetSecurityConfig());
-
appData->EnforceUserTokenRequirement = securityConfig.GetEnforceUserTokenRequirement();
if (securityConfig.AdministrationAllowedSIDsSize() > 0) {
TVector<TString> administrationAllowedSIDs(securityConfig.GetAdministrationAllowedSIDs().begin(), securityConfig.GetAdministrationAllowedSIDs().end());
diff --git a/ydb/core/mind/hive/monitoring.cpp b/ydb/core/mind/hive/monitoring.cpp
index 7e9a83b354e..ecd6a4c2c36 100644
--- a/ydb/core/mind/hive/monitoring.cpp
+++ b/ydb/core/mind/hive/monitoring.cpp
@@ -1495,7 +1495,8 @@ public:
if (down && $(element).hasClass('glyphicon-ok')) {
$(element).removeClass('glyphicon-ok');
element.inProgress = true;
- $.ajax({url:'app?TabletID=' + hiveId + '&node=' + nodeId + '&page=SetDown&down=1', success: function(){ $(element).addClass('glyphicon-remove'); element.inProgress = false; }});
+ $.ajax({url:'app?TabletID=' + hiveId + '&node=' + nodeId + '&page=SetDown&
+ =1', success: function(){ $(element).addClass('glyphicon-remove'); element.inProgress = false; }});
} else if (!down && $(element).hasClass('glyphicon-remove')) {
$(element).removeClass('glyphicon-remove');
element.inProgress = true;
diff --git a/ydb/core/protos/config.proto b/ydb/core/protos/config.proto
index 84d9f9e695f..643c61a92e7 100644
--- a/ydb/core/protos/config.proto
+++ b/ydb/core/protos/config.proto
@@ -217,6 +217,21 @@ message TDomainsConfig {
repeated string DefaultUserSIDs = 4;
optional string AllAuthenticatedUsers = 5;
repeated string ViewerAllowedSIDs = 6;
+
+ message TUser {
+ optional string Name = 1;
+ optional string Password = 2;
+ }
+
+ message TGroup {
+ optional string Name = 1;
+ repeated string Members = 2;
+ }
+
+ repeated TUser DefaultUsers = 15;
+ repeated TGroup DefaultGroups = 16;
+ repeated string DefaultAccess = 17;
+ optional string AllUsersGroup = 18;
}
repeated TDomain Domain = 1;
diff --git a/ydb/core/testlib/test_client.cpp b/ydb/core/testlib/test_client.cpp
index 99cb332737f..67799128cb0 100644
--- a/ydb/core/testlib/test_client.cpp
+++ b/ydb/core/testlib/test_client.cpp
@@ -218,6 +218,7 @@ namespace Tests {
Runtime->GetAppData(nodeIdx).NetClassifierConfig.MergeFrom(Settings->NetClassifierConfig);
Runtime->GetAppData(nodeIdx).StreamingConfig.MergeFrom(Settings->AppConfig.GetGRpcConfig().GetStreamingConfig());
Runtime->GetAppData(nodeIdx).EnforceUserTokenRequirement = Settings->AppConfig.GetDomainsConfig().GetSecurityConfig().GetEnforceUserTokenRequirement();
+ Runtime->GetAppData(nodeIdx).DomainsConfig.MergeFrom(Settings->AppConfig.GetDomainsConfig());
SetupConfigurators(nodeIdx);
SetupProxies(nodeIdx);
}
diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp
index 049afed7ac1..1560794a49d 100644
--- a/ydb/core/tx/schemeshard/schemeshard__init.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp
@@ -1371,7 +1371,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
Y_VERIFY(rootPath->DomainPathId == Self->RootPathId());
Y_VERIFY(!IsStartWithSlash(rootPath->Name));
- Self->RootPathElemets = SplitPath(rootPath->Name);
+ Self->RootPathElements = SplitPath(rootPath->Name);
Y_VERIFY(!rootPath->StepDropped);
Self->PathsById[rootPath->PathId ] = rootPath;
diff --git a/ydb/core/tx/schemeshard/schemeshard__init_root.cpp b/ydb/core/tx/schemeshard/schemeshard__init_root.cpp
index 74399680cda..7085c109a3d 100644
--- a/ydb/core/tx/schemeshard/schemeshard__init_root.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__init_root.cpp
@@ -23,7 +23,6 @@ struct TSchemeShard::TTxInitRoot : public TSchemeShard::TRwTxBase {
const TDomainsInfo::TDomain& selfDomain = Self->GetDomainDescription(ctx);
TString rootName = selfDomain.Name;
- TString owner = BUILTIN_ACL_ROOT;
LOG_NOTICE_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
"TTxInitRoot DoExecute"
@@ -36,9 +35,71 @@ struct TSchemeShard::TTxInitRoot : public TSchemeShard::TRwTxBase {
Y_VERIFY(!Self->IsShemeShardConfigured());
Y_VERIFY_S(!rootName.empty(), "invalid root name in domain config");
- TVector<TString> rootPathElemets = SplitPath(rootName);
- TString joinedRootPath = JoinPath(rootPathElemets);
- Y_VERIFY_S(rootPathElemets.size() == 1, "invalid root name in domain config: " << rootName << " parts count: " << rootPathElemets.size());
+ TVector<TString> rootPathElements = SplitPath(rootName);
+ TString joinedRootPath = JoinPath(rootPathElements);
+ Y_VERIFY_S(rootPathElements.size() == 1, "invalid root name in domain config: " << rootName << " parts count: " << rootPathElements.size());
+
+ TString owner;
+ const NKikimrConfig::TDomainsConfig::TSecurityConfig& securityConfig = Self->GetDomainsConfig().GetSecurityConfig();
+
+ for (const auto& defaultUser : securityConfig.GetDefaultUsers()) {
+ auto response = Self->LoginProvider.CreateUser({
+ .User = defaultUser.GetName(),
+ .Password = defaultUser.GetPassword(),
+ });
+ if (response.Error) {
+ LOG_ERROR_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
+ "TTxInitRoot DoExecute"
+ << ", path: " << rootName
+ << ", error creating user: " << defaultUser.GetName()
+ << ", error: " << response.Error);
+ } else {
+ auto& sid = Self->LoginProvider.Sids[defaultUser.GetName()];
+ db.Table<Schema::LoginSids>().Key(sid.Name).Update<Schema::LoginSids::SidType, Schema::LoginSids::SidHash>(sid.Type, sid.Hash);
+ if (owner.empty()) {
+ owner = defaultUser.GetName();
+ }
+ }
+ }
+
+ for (const auto& defaultGroup : securityConfig.GetDefaultGroups()) {
+ auto response = Self->LoginProvider.CreateGroup({
+ .Group = defaultGroup.GetName(),
+ .Options = {
+ .CheckName = false
+ }
+ });
+ if (response.Error) {
+ LOG_ERROR_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
+ "TTxInitRoot DoExecute"
+ << ", path: " << rootName
+ << ", error creating group: " << defaultGroup.GetName()
+ << ", error: " << response.Error);
+ } else {
+ auto& sid = Self->LoginProvider.Sids[defaultGroup.GetName()];
+ db.Table<Schema::LoginSids>().Key(sid.Name).Update<Schema::LoginSids::SidType>(sid.Type);
+ for (const auto& member : defaultGroup.GetMembers()) {
+ auto response = Self->LoginProvider.AddGroupMembership({
+ .Group = defaultGroup.GetName(),
+ .Member = member,
+ });
+ if (response.Error) {
+ LOG_ERROR_S(ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
+ "TTxInitRoot DoExecute"
+ << ", path: " << rootName
+ << ", error modifying group: " << defaultGroup.GetName()
+ << ", with member: " << member
+ << ", error: " << response.Error);
+ } else {
+ db.Table<Schema::LoginSidMembers>().Key(defaultGroup.GetName(), member).Update();
+ }
+ }
+ }
+ }
+
+ if (owner.empty()) {
+ owner = BUILTIN_ACL_ROOT;
+ }
TPathElement::TPtr newPath = new TPathElement(Self->RootPathId(), Self->RootPathId(), Self->RootPathId(), joinedRootPath, owner);
newPath->CreateTxId = TTxId(1);
@@ -51,18 +112,27 @@ struct TSchemeShard::TTxInitRoot : public TSchemeShard::TRwTxBase {
Self->NextLocalPathId = Self->RootPathId().LocalPathId + 1;
Self->NextLocalShardIdx = 1;
Self->ShardInfos.clear();
- Self->RootPathElemets = std::move(rootPathElemets);
-
+ Self->RootPathElements = std::move(rootPathElements);
TSubDomainInfo::TPtr newDomain = new TSubDomainInfo(0, Self->RootPathId());
newDomain->InitializeAsGlobal(Self->CreateRootProcessingParams(ctx));
Self->SubDomains[Self->RootPathId()] = newDomain;
+ NACLib::TDiffACL diffAcl;
+ for (const auto& defaultAccess : securityConfig.GetDefaultAccess()) {
+ NACLibProto::TACE ace;
+ NACLib::TACL::FromString(ace, defaultAccess);
+ diffAcl.AddAccess(ace);
+ }
+ newPath->ApplyACL(diffAcl.SerializeAsString());
+ newDomain->UpdateSecurityState(Self->LoginProvider.GetSecurityState());
+
Self->PersistUserAttributes(db, Self->RootPathId(), nullptr, newPath->UserAttrs);
Self->PersistPath(db, newPath->PathId);
Self->PersistUpdateNextPathId(db);
Self->PersistUpdateNextShardIdx(db);
Self->PersistStoragePools(db, Self->RootPathId(), *newDomain);
+ Self->PersistACL(db, newPath);
Self->InitState = TTenantInitState::Done;
Self->PersistInitState(db);
@@ -224,9 +294,9 @@ struct TSchemeShard::TTxInitTenantSchemeShard : public TSchemeShard::TRwTxBase {
return;
}
- TVector<TString> rootPathElemets = SplitPath(rootPath);
+ TVector<TString> rootPathElements = SplitPath(rootPath);
- TString joinedRootPath = JoinPath(rootPathElemets);
+ TString joinedRootPath = JoinPath(rootPathElements);
Y_VERIFY(!IsStartWithSlash(joinedRootPath)); //skip lead '/'
@@ -260,7 +330,7 @@ struct TSchemeShard::TTxInitTenantSchemeShard : public TSchemeShard::TRwTxBase {
return;
}
- if (rootPathElemets.size() <= 1) {
+ if (rootPathElements.size() <= 1) {
Reply->Record.SetStatus(NKikimrScheme::StatusInvalidParameter);
return;
}
@@ -284,7 +354,7 @@ struct TSchemeShard::TTxInitTenantSchemeShard : public TSchemeShard::TRwTxBase {
Self->NextLocalShardIdx = 1;
Self->ShardInfos.clear();
- Self->RootPathElemets = std::move(rootPathElemets);
+ Self->RootPathElements = std::move(rootPathElements);
Self->ParentDomainId = TPathId(domainSchemeShard, domainPathId);
Self->ParentDomainOwner = owner;
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
index 0b420f75b41..ecda4b08bfc 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
@@ -30,16 +30,27 @@ public:
if (Transaction.GetWorkingDir() != context.SS->LoginProvider.Audience) {
result->SetStatus(NKikimrScheme::StatusPreconditionFailed, "Wrong working dir");
} else {
+ const NKikimrConfig::TDomainsConfig::TSecurityConfig& securityConfig = context.SS->GetDomainsConfig().GetSecurityConfig();
const NKikimrSchemeOp::TAlterLogin& alterLogin = Transaction.GetAlterLogin();
switch (alterLogin.GetAlterCase()) {
case NKikimrSchemeOp::TAlterLogin::kCreateUser: {
const auto& createUser = alterLogin.GetCreateUser();
- auto response = context.SS->LoginProvider.CreateUser({.User = createUser.GetUser(), .Password = createUser.GetPassword()});
+ auto response = context.SS->LoginProvider.CreateUser(
+ {.User = createUser.GetUser(), .Password = createUser.GetPassword()});
if (response.Error) {
result->SetStatus(NKikimrScheme::StatusPreconditionFailed, response.Error);
} else {
auto& sid = context.SS->LoginProvider.Sids[createUser.GetUser()];
db.Table<Schema::LoginSids>().Key(sid.Name).Update<Schema::LoginSids::SidType, Schema::LoginSids::SidHash>(sid.Type, sid.Hash);
+ if (securityConfig.HasAllUsersGroup()) {
+ auto response = context.SS->LoginProvider.AddGroupMembership({
+ .Group = securityConfig.GetAllUsersGroup(),
+ .Member = createUser.GetUser(),
+ });
+ if (!response.Error) {
+ db.Table<Schema::LoginSidMembers>().Key(securityConfig.GetAllUsersGroup(), createUser.GetUser()).Update();
+ }
+ }
result->SetStatus(NKikimrScheme::StatusSuccess);
}
break;
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
index 422a71af6fa..640c0b0775c 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
@@ -3673,6 +3673,11 @@ const TDomainsInfo::TDomain& TSchemeShard::GetDomainDescription(const TActorCont
return domain;
}
+const NKikimrConfig::TDomainsConfig& TSchemeShard::GetDomainsConfig() {
+ Y_VERIFY(AppData());
+ return AppData()->DomainsConfig;
+}
+
NKikimrSubDomains::TProcessingParams TSchemeShard::CreateRootProcessingParams(const TActorContext &ctx) {
const auto& domain = GetDomainDescription(ctx);
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h
index 473f3257200..a2954065d07 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.h
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.h
@@ -140,7 +140,7 @@ public:
TParentDomainLink ParentDomainLink;
TSubDomainsLinks SubDomainsLinks;
- TVector<TString> RootPathElemets;
+ TVector<TString> RootPathElements;
THashMap<TPathId, TPathElement::TPtr> PathsById;
TLocalPathId NextLocalPathId = 0;
@@ -1077,6 +1077,8 @@ private:
static NTabletPipe::TClientConfig GetPipeClientConfig();
public:
+ static const NKikimrConfig::TDomainsConfig& GetDomainsConfig();
+
static constexpr NKikimrServices::TActivity::EType ActorActivityType() {
return NKikimrServices::TActivity::FLAT_SCHEMESHARD_ACTOR;
}
diff --git a/ydb/core/tx/schemeshard/schemeshard_path.cpp b/ydb/core/tx/schemeshard/schemeshard_path.cpp
index 7535ee673c8..94e8e4f2140 100644
--- a/ydb/core/tx/schemeshard/schemeshard_path.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_path.cpp
@@ -1173,11 +1173,11 @@ TPath& TPath::Dive(const TString& name) {
return *this;
}
- if (Elements.empty() && NameParts.size() < SS->RootPathElemets.size()) {
+ if (Elements.empty() && NameParts.size() < SS->RootPathElements.size()) {
NameParts.push_back(name);
- if (NameParts.size() == SS->RootPathElemets.size()
- && NameParts == SS->RootPathElemets)
+ if (NameParts.size() == SS->RootPathElements.size()
+ && NameParts == SS->RootPathElements)
{
Elements = {SS->PathsById.at(SS->RootPathId())};
NameParts = {Elements.front()->Name};
@@ -1246,7 +1246,7 @@ TPath TPath::ResolveWithInactive(TOperationId opId, const TString path, TSchemeS
TPath headOpPath = Init(txState->TargetPathId, ss);
- auto headPathNameParts = ss->RootPathElemets;
+ auto headPathNameParts = ss->RootPathElements;
headPathNameParts.insert(headPathNameParts.end(), std::next(headOpPath.NameParts.begin()), headOpPath.NameParts.end());
if (headPathNameParts.size() + 1 == pathParts.size()
diff --git a/ydb/library/aclib/aclib.cpp b/ydb/library/aclib/aclib.cpp
index 946497ea303..d1fa5a1a925 100644
--- a/ydb/library/aclib/aclib.cpp
+++ b/ydb/library/aclib/aclib.cpp
@@ -16,7 +16,7 @@ std::pair<ui32, ui32>& operator |=(std::pair<ui32, ui32>& a, const std::pair<ui3
void TUserToken::SetGroupSIDs(const TVector<TString>& groupSIDs) {
auto& hashTable = *MutableGroupSIDs();
auto& hashBuckets = *hashTable.MutableBuckets();
- int size(groupSIDs.size()); // we targeting for load factor ~1.0
+ int size(groupSIDs.size()); // we are targeting for load factor of ~1.0
hashBuckets.Reserve(size);
for (int i = 0; i < size; ++i) {
hashBuckets.Add();
@@ -138,7 +138,7 @@ TSecurityObject::TSecurityObject(const TSID& owner, bool isContainer)
ui32 TSecurityObject::GetEffectiveAccessRights(const TUserToken& user) const {
if (HasOwnerSID() && user.IsExist(GetOwnerSID()))
- return EAccessRights::GenericFull; // the owner always have access
+ return EAccessRights::GenericFull; // the owner always has access
ui32 deniedAccessRights = EAccessRights::NoAccess;
ui32 allowedAccessRights = EAccessRights::NoAccess;
if (HasACL()) {
@@ -162,7 +162,7 @@ ui32 TSecurityObject::GetEffectiveAccessRights(const TUserToken& user) const {
bool TSecurityObject::CheckAccess(ui32 access, const TUserToken& user) const {
if (HasOwnerSID() && user.IsExist(GetOwnerSID()))
- return true; // the owner always have access
+ return true; // the owner always has access
if (HasACL()) {
ui32 accessRightsLeft = access;
for (const NACLibProto::TACE& ace : GetACL().GetACE()) {
@@ -174,10 +174,10 @@ bool TSecurityObject::CheckAccess(ui32 access, const TUserToken& user) const {
return false; // deny entries have precedence over allow entries
break;
case EAccessType::Allow:
- accessRightsLeft &= ~(accessRightsLeft & ace.GetAccessRight()); // some rights allowed
+ accessRightsLeft &= ~(accessRightsLeft & ace.GetAccessRight()); // some rights are allowed
break;
}
- if (accessRightsLeft == 0) // all rights has been allowed
+ if (accessRightsLeft == 0) // all rights have been allowed
return true;
}
}
diff --git a/ydb/library/login/login.cpp b/ydb/library/login/login.cpp
index b6fbc3c8f63..168d11a1ade 100644
--- a/ydb/library/login/login.cpp
+++ b/ydb/library/login/login.cpp
@@ -115,7 +115,7 @@ TLoginProvider::TRemoveUserResponse TLoginProvider::RemoveUser(const TRemoveUser
TLoginProvider::TBasicResponse TLoginProvider::CreateGroup(const TCreateGroupRequest& request) {
TBasicResponse response;
- if (!CheckAllowedName(request.Group)) {
+ if (request.Options.CheckName && !CheckAllowedName(request.Group)) {
response.Error = "Name is not allowed";
return response;
}
diff --git a/ydb/library/login/login.h b/ydb/library/login/login.h
index c56f5a22883..96ef5d83183 100644
--- a/ydb/library/login/login.h
+++ b/ydb/library/login/login.h
@@ -77,7 +77,12 @@ public:
};
struct TCreateGroupRequest : TBasicRequest {
+ struct TOptions {
+ bool CheckName = true;
+ };
+
TString Group;
+ TOptions Options;
};
struct TAddGroupMembershipRequest : TBasicRequest {
diff --git a/ydb/library/yaml_config/yaml_config_parser.cpp b/ydb/library/yaml_config/yaml_config_parser.cpp
index 148a4271aca..f292f1cc010 100644
--- a/ydb/library/yaml_config/yaml_config_parser.cpp
+++ b/ydb/library/yaml_config/yaml_config_parser.cpp
@@ -563,6 +563,103 @@ namespace NKikimr::NYaml {
}
}
+ void PrepareSecurityConfig(NJson::TJsonValue& json) {
+ Y_ENSURE(json.Has("domains_config"));
+ Y_ENSURE(json["domains_config"].IsMap());
+
+ NJson::TJsonValue& domainsConfig = json["domains_config"];
+ NJson::TJsonValue& securityConfig = domainsConfig["security_config"];
+ TString defaultUserName;
+
+ if (securityConfig.Has("default_users")) {
+ NJson::TJsonValue& defaultUsers = securityConfig["default_users"];
+ Y_ENSURE(defaultUsers.IsArray());
+ Y_ENSURE(defaultUsers.GetArraySafe().size() > 0);
+ NJson::TJsonValue& defaultUser = defaultUsers.GetArraySafe()[0];
+ Y_ENSURE(defaultUser.IsMap());
+ defaultUserName = defaultUser["password"].GetStringRobust();
+ } else {
+ NJson::TJsonValue& defaultUser = securityConfig["default_users"].AppendValue({});
+ defaultUser["name"] = defaultUserName = "root";
+ defaultUser["password"] = "";
+ }
+
+ if (!securityConfig.Has("default_groups")) {
+ NJson::TJsonValue& defaultGroups = securityConfig["default_groups"];
+
+ {
+ NJson::TJsonValue& defaultGroupAdmins = defaultGroups.AppendValue({});
+ defaultGroupAdmins["name"] = "ADMINS";
+ defaultGroupAdmins["members"].AppendValue(defaultUserName);
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupDatabaseAdmins = defaultGroups.AppendValue({});
+ defaultGroupDatabaseAdmins["name"] = "DATABASE-ADMINS";
+ defaultGroupDatabaseAdmins["members"].AppendValue("ADMINS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupAccessAdmins = defaultGroups.AppendValue({});
+ defaultGroupAccessAdmins["name"] = "ACCESS-ADMINS";
+ defaultGroupAccessAdmins["members"].AppendValue("DATABASE-ADMINS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupDdlAdmins = defaultGroups.AppendValue({});
+ defaultGroupDdlAdmins["name"] = "DDL-ADMINS";
+ defaultGroupDdlAdmins["members"].AppendValue("DATABASE-ADMINS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupDataWriters = defaultGroups.AppendValue({});
+ defaultGroupDataWriters["name"] = "DATA-WRITERS";
+ defaultGroupDataWriters["members"].AppendValue("ADMINS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupDataReaders = defaultGroups.AppendValue({});
+ defaultGroupDataReaders["name"] = "DATA-READERS";
+ defaultGroupDataReaders["members"].AppendValue("DATA-WRITERS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupMetadataReaders = defaultGroups.AppendValue({});
+ defaultGroupMetadataReaders["name"] = "METADATA-READERS";
+ defaultGroupMetadataReaders["members"].AppendValue("DATA-READERS");
+ defaultGroupMetadataReaders["members"].AppendValue("DDL-ADMINS");
+ }
+
+ {
+ NJson::TJsonValue& defaultGroupUsers = defaultGroups.AppendValue({});
+ defaultGroupUsers["name"] = "USERS";
+ defaultGroupUsers["members"].AppendValue("METADATA-READERS");
+ defaultGroupUsers["members"].AppendValue("DATA-READERS");
+ defaultGroupUsers["members"].AppendValue("DATA-WRITERS");
+ defaultGroupUsers["members"].AppendValue("DDL-ADMINS");
+ defaultGroupUsers["members"].AppendValue("ACCESS-ADMINS");
+ defaultGroupUsers["members"].AppendValue("DATABASE-ADMINS");
+ defaultGroupUsers["members"].AppendValue("ADMINS");
+ defaultGroupUsers["members"].AppendValue(defaultUserName);
+ }
+ }
+
+ if (!securityConfig.Has("all_users_group")) {
+ securityConfig["all_users_group"] = "USERS";
+ }
+
+ if (!securityConfig.Has("default_access")) {
+ NJson::TJsonValue& defaultAccess = securityConfig["default_access"];
+ defaultAccess.AppendValue("+(ConnDB):USERS"); // ConnectDatabase
+ defaultAccess.AppendValue("+(DS|RA):METADATA-READERS"); // DescribeSchema | ReadAttributes
+ defaultAccess.AppendValue("+(SR):DATA-READERS"); // SelectRow
+ defaultAccess.AppendValue("+(UR|ER):DATA-WRITERS"); // UpdateRow | EraseRow
+ defaultAccess.AppendValue("+(CD|CT|WA|AS|RS):DDL-ADMINS"); // CreateDirectory | CreateTable | WriteAttributes | AlterSchema | RemoveSchema
+ defaultAccess.AppendValue("+(GAR):ACCESS-ADMINS"); // GrantAccessRights
+ defaultAccess.AppendValue("+(CDB|DDB):DATABASE-ADMINS"); // CreateDatabase | DropDatabase
+ }
+ }
+
void PrepareNameserviceConfig(NJson::TJsonValue& json) {
if (json.Has("nameservice_config")) {
Y_ENSURE(json["nameservice_config"].IsMap());
@@ -650,6 +747,7 @@ namespace NKikimr::NYaml {
PrepareLogConfig(json);
PrepareSystemTabletsInfo(json);
PrepareDomainsConfig(json);
+ PrepareSecurityConfig(json);
PrepareBootstrapConfig(json);
ClearFields(json);
}
diff --git a/ydb/tests/functional/ydb_cli/ya.make b/ydb/tests/functional/ydb_cli/ya.make
index cf8d4dae484..52de4170be6 100644
--- a/ydb/tests/functional/ydb_cli/ya.make
+++ b/ydb/tests/functional/ydb_cli/ya.make
@@ -7,7 +7,6 @@ TEST_SRCS(
test_ydb_scripting.py
)
-ENV(YDB_TOKEN="root@builtin")
ENV(YDB_DRIVER_BINARY="ydb/apps/ydbd/ydbd")
TIMEOUT(600)
SIZE(MEDIUM)