diff options
author | ijon <ijon@ydb.tech> | 2023-09-27 17:10:40 +0300 |
---|---|---|
committer | ijon <ijon@ydb.tech> | 2023-09-27 17:55:00 +0300 |
commit | 9472c1bd8bbcdca676da3dcc72772ab13d8d7857 (patch) | |
tree | 9c69a073222dec8815fd06749973830574f7e1e1 | |
parent | 54ce98c42f381b12614dd327dc58a129a661c70b (diff) | |
download | ydb-9472c1bd8bbcdca676da3dcc72772ab13d8d7857.tar.gz |
auditlog, schemeshard: add DML audit settings
Support DML audit settings at a database level (Create/Alter *Subdomain).
KIKIMR-18697
31 files changed, 878 insertions, 19 deletions
diff --git a/.mapping.json b/.mapping.json index 3f36dbd246..83359369f1 100644 --- a/.mapping.json +++ b/.mapping.json @@ -5686,6 +5686,11 @@ "ydb/core/tx/schemeshard/CMakeLists.linux-x86_64.txt":"", "ydb/core/tx/schemeshard/CMakeLists.txt":"", "ydb/core/tx/schemeshard/CMakeLists.windows-x86_64.txt":"", + "ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.darwin-x86_64.txt":"", + "ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-aarch64.txt":"", + "ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-x86_64.txt":"", + "ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.txt":"", + "ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.windows-x86_64.txt":"", "ydb/core/tx/schemeshard/ut_backup/CMakeLists.darwin-x86_64.txt":"", "ydb/core/tx/schemeshard/ut_backup/CMakeLists.linux-aarch64.txt":"", "ydb/core/tx/schemeshard/ut_backup/CMakeLists.linux-x86_64.txt":"", diff --git a/ydb/core/protos/flat_tx_scheme.proto b/ydb/core/protos/flat_tx_scheme.proto index eab789772c..ca31a4039d 100644 --- a/ydb/core/protos/flat_tx_scheme.proto +++ b/ydb/core/protos/flat_tx_scheme.proto @@ -211,6 +211,7 @@ message TEvInitTenantSchemeShard { optional NKikimrSubDomains.TSchemeQuotas DeclaredSchemeQuotas = 16; optional Ydb.Cms.DatabaseQuotas DatabaseQuotas = 17; + optional NKikimrSubDomains.TAuditSettings AuditSettings = 18; } message TEvInitTenantSchemeShardResult { @@ -378,6 +379,8 @@ message TEvUpdateTenantSchemeShard { optional Ydb.Cms.DatabaseQuotas DatabaseQuotas = 14; optional string UpdateTenantRootACL = 13; + + optional NKikimrSubDomains.TAuditSettings AuditSettings = 15; } message TEvFindTabletSubDomainPathId { diff --git a/ydb/core/protos/subdomains.proto b/ydb/core/protos/subdomains.proto index cd51c78e2a..83490ca6d2 100644 --- a/ydb/core/protos/subdomains.proto +++ b/ydb/core/protos/subdomains.proto @@ -22,6 +22,7 @@ message TSubDomainSettings { optional bool ExternalSysViewProcessor = 10 [default = false]; optional TSchemeQuotas DeclaredSchemeQuotas = 11; optional Ydb.Cms.DatabaseQuotas DatabaseQuotas = 12; + optional TAuditSettings AuditSettings = 13; } message TProcessingParams { @@ -66,7 +67,7 @@ message TDomainState { } message TAuditSettings { - optional bool EnableDmlAudit = 1; + optional bool EnableDmlAudit = 1 [default = false]; repeated string ExpectedSubjects = 2; } diff --git a/ydb/core/tx/schemeshard/CMakeLists.darwin-x86_64.txt b/ydb/core/tx/schemeshard/CMakeLists.darwin-x86_64.txt index 36b49b2cb7..e69d303b7a 100644 --- a/ydb/core/tx/schemeshard/CMakeLists.darwin-x86_64.txt +++ b/ydb/core/tx/schemeshard/CMakeLists.darwin-x86_64.txt @@ -6,6 +6,7 @@ # original buildsystem will not be accepted. +add_subdirectory(ut_auditsettings) add_subdirectory(ut_backup) add_subdirectory(ut_base) add_subdirectory(ut_base_reboots) diff --git a/ydb/core/tx/schemeshard/CMakeLists.linux-aarch64.txt b/ydb/core/tx/schemeshard/CMakeLists.linux-aarch64.txt index e68f7ce937..2a9e71ef80 100644 --- a/ydb/core/tx/schemeshard/CMakeLists.linux-aarch64.txt +++ b/ydb/core/tx/schemeshard/CMakeLists.linux-aarch64.txt @@ -6,6 +6,7 @@ # original buildsystem will not be accepted. +add_subdirectory(ut_auditsettings) add_subdirectory(ut_backup) add_subdirectory(ut_base) add_subdirectory(ut_base_reboots) diff --git a/ydb/core/tx/schemeshard/CMakeLists.linux-x86_64.txt b/ydb/core/tx/schemeshard/CMakeLists.linux-x86_64.txt index e68f7ce937..2a9e71ef80 100644 --- a/ydb/core/tx/schemeshard/CMakeLists.linux-x86_64.txt +++ b/ydb/core/tx/schemeshard/CMakeLists.linux-x86_64.txt @@ -6,6 +6,7 @@ # original buildsystem will not be accepted. +add_subdirectory(ut_auditsettings) add_subdirectory(ut_backup) add_subdirectory(ut_base) add_subdirectory(ut_base_reboots) diff --git a/ydb/core/tx/schemeshard/CMakeLists.windows-x86_64.txt b/ydb/core/tx/schemeshard/CMakeLists.windows-x86_64.txt index e41a3f675b..b27ba39942 100644 --- a/ydb/core/tx/schemeshard/CMakeLists.windows-x86_64.txt +++ b/ydb/core/tx/schemeshard/CMakeLists.windows-x86_64.txt @@ -6,6 +6,7 @@ # original buildsystem will not be accepted. +add_subdirectory(ut_auditsettings) add_subdirectory(ut_backup) add_subdirectory(ut_base) add_subdirectory(ut_base_reboots) diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp index 36b3c78eee..ab83c052a6 100644 --- a/ydb/core/tx/schemeshard/schemeshard__init.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp @@ -1524,6 +1524,12 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> { if (domainInfo->GetDiskQuotaExceeded()) { Self->ChangeDiskSpaceQuotaExceeded(+1); } + + if (rowset.HaveValue<Schema::SubDomains::AuditSettings>()) { + NKikimrSubDomains::TAuditSettings value; + Y_VERIFY(ParseFromStringNoSizeLimit(value, rowset.GetValue<Schema::SubDomains::AuditSettings>())); + domainInfo->SetAuditSettings(value); + } } if (!rowset.Next()) diff --git a/ydb/core/tx/schemeshard/schemeshard__init_root.cpp b/ydb/core/tx/schemeshard/schemeshard__init_root.cpp index 6d37d4f2e7..4660444414 100644 --- a/ydb/core/tx/schemeshard/schemeshard__init_root.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__init_root.cpp @@ -392,6 +392,10 @@ struct TSchemeShard::TTxInitTenantSchemeShard : public TSchemeShard::TRwTxBase { subdomain->SetDatabaseQuotas(record.GetDatabaseQuotas(), Self); } + if (record.HasAuditSettings()) { + subdomain->SetAuditSettings(record.GetAuditSettings()); + } + RegisterShard(db, subdomain, processingParams.GetCoordinators(), TTabletTypes::Coordinator); RegisterShard(db, subdomain, processingParams.GetMediators(), TTabletTypes::Mediator); RegisterShard(db, subdomain, TVector<ui64>{processingParams.GetSchemeShard()}, TTabletTypes::SchemeShard); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_extsubdomain.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_extsubdomain.cpp index cdb070e4f0..a690454a47 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_extsubdomain.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_extsubdomain.cpp @@ -794,6 +794,13 @@ public: alter->SetDatabaseQuotas(inputSettings.GetDatabaseQuotas()); } + if (const auto& auditSettings = subdomainInfo->GetAuditSettings()) { + alter->SetAuditSettings(*auditSettings); + } + if (inputSettings.HasAuditSettings()) { + alter->ApplyAuditSettings(inputSettings.GetAuditSettings()); + } + LOG_D("TAlterExtSubDomain Propose" << ", opId: " << OperationId << ", subdomain ver " << subdomainInfo->GetVersion() diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_subdomain.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_subdomain.cpp index 39000ffb62..c4f30ba670 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_subdomain.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_subdomain.cpp @@ -290,6 +290,13 @@ public: alterData->SetDatabaseQuotas(settings.GetDatabaseQuotas()); } + if (const auto& auditSettings = subDomainInfo->GetAuditSettings()) { + alterData->SetAuditSettings(*auditSettings); + } + if (settings.HasAuditSettings()) { + alterData->ApplyAuditSettings(settings.GetAuditSettings()); + } + NIceDb::TNiceDb db(context.GetDB()); subDomain->LastTxId = OperationId.GetTxId(); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_common_subdomain.h b/ydb/core/tx/schemeshard/schemeshard__operation_common_subdomain.h index f94c27897f..9e9eee08f6 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_common_subdomain.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_common_subdomain.h @@ -232,6 +232,9 @@ public: if (alterData->GetDatabaseQuotas()) { event->Record.MutableDatabaseQuotas()->CopyFrom(*alterData->GetDatabaseQuotas()); } + if (alterData->GetAuditSettings()) { + event->Record.MutableAuditSettings()->CopyFrom(*alterData->GetAuditSettings()); + } LOG_DEBUG_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "Send configure request to schemeshard: " << tabletID << " opId: " << OperationId << diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_create_extsubdomain.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_create_extsubdomain.cpp index 19ece7b117..0c61d6c8b5 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_create_extsubdomain.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_create_extsubdomain.cpp @@ -156,7 +156,6 @@ public: return result; } - bool requestedStoragePools = !settings.GetStoragePools().empty(); if (requestedStoragePools) { return paramErrorResult("only declaration at creation is allowed, do not set up storage"); @@ -228,6 +227,10 @@ public: alter->SetDatabaseQuotas(settings.GetDatabaseQuotas()); } + if (settings.HasAuditSettings()) { + alter->SetAuditSettings(settings.GetAuditSettings()); + } + Y_VERIFY(!context.SS->SubDomains.contains(newNode->PathId)); auto& subDomainInfo = context.SS->SubDomains[newNode->PathId]; subDomainInfo = new TSubDomainInfo(); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_create_subdomain.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_create_subdomain.cpp index f5a58df674..56af6981bf 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_create_subdomain.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_create_subdomain.cpp @@ -298,6 +298,10 @@ public: alter->SetDatabaseQuotas(settings.GetDatabaseQuotas()); } + if (settings.HasAuditSettings()) { + alter->SetAuditSettings(settings.GetAuditSettings()); + } + Y_VERIFY(!context.SS->SubDomains.contains(newNode->PathId)); auto& subDomainInfo = context.SS->SubDomains[newNode->PathId]; subDomainInfo = new TSubDomainInfo(); diff --git a/ydb/core/tx/schemeshard/schemeshard__sync_update_tenants.cpp b/ydb/core/tx/schemeshard/schemeshard__sync_update_tenants.cpp index a74b28a6be..58455f5f41 100644 --- a/ydb/core/tx/schemeshard/schemeshard__sync_update_tenants.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__sync_update_tenants.cpp @@ -8,7 +8,6 @@ namespace NSchemeShard { using namespace NTabletFlatExecutor; - struct TSchemeShard::TTxSyncTenant : public TSchemeShard::TRwTxBase { TPathId PathId; TSideEffects SideEffects; @@ -114,6 +113,11 @@ struct TSchemeShard::TTxUpdateTenant : public TSchemeShard::TRwTxBase { Self->PersistSubDomainDatabaseQuotas(db, Self->RootPathId(), *subdomain); } + if (record.HasAuditSettings()) { + subdomain->SetAuditSettings(record.GetAuditSettings()); + Self->PersistSubDomainAuditSettings(db, Self->RootPathId(), *subdomain); + } + Self->PersistStoragePools(db, Self->RootPathId(), *subdomain); SideEffects.PublishToSchemeBoard(InvalidOperationId, Self->RootPathId()); MakeSync(); diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp index 5c2c98b036..4c9d406e4d 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp @@ -54,7 +54,7 @@ bool ResolvePoolNames( return true; } -} // namespace +} // anonymous namespace const TSchemeLimits TSchemeShard::DefaultLimits = {}; @@ -1878,6 +1878,8 @@ void TSchemeShard::PersistSubDomainAlter(NIceDb::TNiceDb& db, const TPathId& pat NIceDb::TNull<Schema::SubDomainsAlterData::DatabaseQuotas>()); } + PersistSubDomainAuditSettingsAlter(db, pathId, subDomain); + for (auto shardIdx: subDomain.GetPrivateShards()) { db.Table<Schema::SubDomainShardsAlterData>().Key(pathId.LocalPathId, shardIdx.GetLocalId()).Update(); } @@ -1939,6 +1941,8 @@ void TSchemeShard::PersistSubDomain(NIceDb::TNiceDb& db, const TPathId& pathId, PersistSubDomainDatabaseQuotas(db, pathId, subDomain); PersistSubDomainState(db, pathId, subDomain); + PersistSubDomainAuditSettings(db, pathId, subDomain); + db.Table<Schema::SubDomainsAlterData>().Key(pathId.LocalPathId).Delete(); for (auto shardIdx: subDomain.GetPrivateShards()) { @@ -2040,6 +2044,26 @@ void TSchemeShard::PersistRemoveSubDomain(NIceDb::TNiceDb& db, const TPathId& pa } } +template <class Table> +void PersistSubDomainAuditSettingsImpl(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo::TMaybeAuditSettings& value) { + using Field = typename Table::AuditSettings; + if (value) { + TString serialized; + Y_VERIFY(value->SerializeToString(&serialized)); + db.Table<Table>().Key(pathId.LocalPathId).Update(NIceDb::TUpdate<Field>(serialized)); + } else { + db.Table<Table>().Key(pathId.LocalPathId).template UpdateToNull<Field>(); + } +} + +void TSchemeShard::PersistSubDomainAuditSettings(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain) { + PersistSubDomainAuditSettingsImpl<Schema::SubDomains>(db, pathId, subDomain.GetAuditSettings()); +} + +void TSchemeShard::PersistSubDomainAuditSettingsAlter(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain) { + PersistSubDomainAuditSettingsImpl<Schema::SubDomainsAlterData>(db, pathId, subDomain.GetAuditSettings()); +} + void TSchemeShard::PersistACL(NIceDb::TNiceDb& db, const TPathElement::TPtr path) { if (path->PathId.OwnerId == TabletID()) { db.Table<Schema::Paths>().Key(path->PathId.LocalPathId).Update( @@ -6060,8 +6084,8 @@ void TSchemeShard::Handle(TEvSchemeShard::TEvNotifyTxCompletionResult::TPtr& ev, "Message:\n" << ev->Get()->Record.ShortDebugString()); const auto txId = TTxId(ev->Get()->Record.GetTxId()); - bool executed = false; - + bool executed = false; + if (TxIdToExport.contains(txId) || TxIdToDependentExport.contains(txId)) { Execute(CreateTxProgressExport(txId), ctx); executed = true; diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h index 49a1ce4e40..a73da994ec 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.h +++ b/ydb/core/tx/schemeshard/schemeshard_impl.h @@ -659,6 +659,8 @@ public: void PersistSubDomainSecurityStateVersion(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain); void PersistSubDomainPrivateShards(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain); void PersistDeleteSubDomainAlter(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain); + void PersistSubDomainAuditSettings(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain); + void PersistSubDomainAuditSettingsAlter(NIceDb::TNiceDb& db, const TPathId& pathId, const TSubDomainInfo& subDomain); void PersistKesusInfo(NIceDb::TNiceDb& db, TPathId pathId, const TKesusInfo::TPtr); void PersistKesusVersion(NIceDb::TNiceDb& db, TPathId pathId, const TKesusInfo::TPtr); void PersistAddKesusAlter(NIceDb::TNiceDb& db, TPathId pathId, const TKesusInfo::TPtr); diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp index ff64a0c82e..6499a34226 100644 --- a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp @@ -20,6 +20,30 @@ namespace NKikimr { namespace NSchemeShard { +void TSubDomainInfo::ApplyAuditSettings(const TSubDomainInfo::TMaybeAuditSettings& diff) { + if (diff.Defined()) { + const auto& input = diff.GetRef(); + if (AuditSettings.Defined()) { + NKikimrSubDomains::TAuditSettings next = AuditSettings.GetRef(); + if (input.HasEnableDmlAudit()) { + next.SetEnableDmlAudit(input.GetEnableDmlAudit()); + } + if (input.ExpectedSubjectsSize() > 0) { + next.ClearExpectedSubjects(); + // instead of CopyFrom, manually copy all but empty elements + for (const auto& i : input.GetExpectedSubjects()) { + if (!i.empty()) { + next.AddExpectedSubjects(i); + } + } + } + AuditSettings = next; + } else { + AuditSettings = input; + } + } +} + TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData( TPtr source, NKikimrSchemeOp::TTableDescription& op, diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.h b/ydb/core/tx/schemeshard/schemeshard_info_types.h index 7648ab37c7..b1323ab699 100644 --- a/ydb/core/tx/schemeshard/schemeshard_info_types.h +++ b/ydb/core/tx/schemeshard/schemeshard_info_types.h @@ -1684,7 +1684,6 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> { CountDiskSpaceQuotas(counters, GetDiskSpaceQuotas(), AlterData->GetDiskSpaceQuotas()); CountStreamShardsQuota(counters, GetStreamShardsQuota(), AlterData->GetStreamShardsQuota()); CountStreamReservedStorageQuota(counters, GetStreamReservedStorageQuota(), AlterData->GetStreamReservedStorageQuota()); - } ui64 GetStreamShardsQuota() const { @@ -2105,6 +2104,18 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> { ++SecurityStateVersion; } + using TMaybeAuditSettings = TMaybe<NKikimrSubDomains::TAuditSettings, NMaybe::TPolicyUndefinedFail>; + + void SetAuditSettings(const NKikimrSubDomains::TAuditSettings& value) { + AuditSettings.ConstructInPlace(value); + } + + const TMaybeAuditSettings& GetAuditSettings() const { + return AuditSettings; + } + + void ApplyAuditSettings(const TMaybeAuditSettings& diff); + private: bool InitiatedAsGlobal = false; NKikimrSubDomains::TProcessingParams ProcessingParams; @@ -2138,6 +2149,8 @@ private: NLoginProto::TSecurityState SecurityState; ui64 SecurityStateVersion = 0; + TMaybeAuditSettings AuditSettings; + TVector<TTabletId> FilterPrivateTablets(TTabletTypes::EType type, const THashMap<TShardIdx, TShardInfo>& allShards) const { TVector<TTabletId> tablets; for (auto shardId: PrivateShards) { @@ -2985,7 +2998,7 @@ struct TIndexBuildInfo: public TSimpleRefCount<TIndexBuildInfo> { TString IndexName; TVector<TString> IndexColumns; TVector<TString> DataColumns; - + TVector<TColumnBuildInfo> BuildColumns; TString ImplTablePath; diff --git a/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp b/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp index 0c58a0e3be..fdba0a3e56 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp @@ -708,6 +708,10 @@ void TPathDescriber::DescribeDomainRoot(TPathElement::TPtr pathEl) { if (subDomainInfo->GetDiskQuotaExceeded()) { entry->MutableDomainState()->SetDiskQuotaExceeded(true); } + + if (const auto& auditSettings = subDomainInfo->GetAuditSettings()) { + entry->MutableAuditSettings()->CopyFrom(*auditSettings); + } } void TPathDescriber::DescribeDomainExtra(TPathElement::TPtr pathEl) { diff --git a/ydb/core/tx/schemeshard/schemeshard_schema.h b/ydb/core/tx/schemeshard/schemeshard_schema.h index 46d38614af..009229dbac 100644 --- a/ydb/core/tx/schemeshard/schemeshard_schema.h +++ b/ydb/core/tx/schemeshard/schemeshard_schema.h @@ -734,6 +734,7 @@ struct Schema : NIceDb::Schema { struct TableCdcStreamsLimit : Column<27, NScheme::NTypeIds::Uint64> {}; struct ExportsLimit : Column<28, NScheme::NTypeIds::Uint64> {}; struct ImportsLimit : Column<29, NScheme::NTypeIds::Uint64> {}; + struct AuditSettings : Column<30, NScheme::NTypeIds::String> {}; using TKey = TableKey<PathId>; using TColumns = TableColumns< @@ -765,7 +766,8 @@ struct Schema : NIceDb::Schema { SecurityStateVersion, TableCdcStreamsLimit, ExportsLimit, - ImportsLimit + ImportsLimit, + AuditSettings >; }; @@ -787,6 +789,7 @@ struct Schema : NIceDb::Schema { struct SharedHiveId : Column<7, NScheme::NTypeIds::Uint64> { using Type = TTabletId; static constexpr Type Default = InvalidTabletId; }; struct DeclaredSchemeQuotas : Column<8, NScheme::NTypeIds::String> {}; struct DatabaseQuotas : Column<9, NScheme::NTypeIds::String> {}; + struct AuditSettings : Column<10, NScheme::NTypeIds::String> {}; using TKey = TableKey<PathId>; using TColumns = TableColumns< @@ -798,7 +801,8 @@ struct Schema : NIceDb::Schema { ResourcesDomainLocalPathId, SharedHiveId, DeclaredSchemeQuotas, - DatabaseQuotas + DatabaseQuotas, + AuditSettings >; }; diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.darwin-x86_64.txt b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.darwin-x86_64.txt new file mode 100644 index 0000000000..d6cb0d8415 --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.darwin-x86_64.txt @@ -0,0 +1,83 @@ + +# This file was generated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_executable(ydb-core-tx-schemeshard-ut_auditsettings) +target_compile_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard +) +target_link_libraries(ydb-core-tx-schemeshard-ut_auditsettings PUBLIC + contrib-libs-cxxsupp + yutil + library-cpp-cpuid_check + cpp-testing-unittest_main + core-tx-schemeshard + library-cpp-getopt + cpp-regex-pcre + library-cpp-svnversion + core-testlib-default + ydb-core-tx + tx-schemeshard-ut_helpers +) +target_link_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -Wl,-platform_version,macos,11.0,11.0 + -fPIC + -fPIC + -framework + CoreFoundation +) +target_sources(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp +) +set_property( + TARGET + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + SPLIT_FACTOR + 10 +) +add_yunittest( + NAME + ydb-core-tx-schemeshard-ut_auditsettings + TEST_TARGET + ydb-core-tx-schemeshard-ut_auditsettings + TEST_ARG + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + LABELS + MEDIUM +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + PROCESSORS + 1 +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + TIMEOUT + 60 +) +target_allocator(ydb-core-tx-schemeshard-ut_auditsettings + system_allocator +) +vcs_info(ydb-core-tx-schemeshard-ut_auditsettings) diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-aarch64.txt b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-aarch64.txt new file mode 100644 index 0000000000..d89d672282 --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-aarch64.txt @@ -0,0 +1,86 @@ + +# This file was generated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_executable(ydb-core-tx-schemeshard-ut_auditsettings) +target_compile_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard +) +target_link_libraries(ydb-core-tx-schemeshard-ut_auditsettings PUBLIC + contrib-libs-linux-headers + contrib-libs-cxxsupp + yutil + cpp-testing-unittest_main + core-tx-schemeshard + library-cpp-getopt + cpp-regex-pcre + library-cpp-svnversion + core-testlib-default + ydb-core-tx + tx-schemeshard-ut_helpers +) +target_link_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -ldl + -lrt + -Wl,--no-as-needed + -fPIC + -fPIC + -lpthread + -lrt + -ldl +) +target_sources(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp +) +set_property( + TARGET + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + SPLIT_FACTOR + 10 +) +add_yunittest( + NAME + ydb-core-tx-schemeshard-ut_auditsettings + TEST_TARGET + ydb-core-tx-schemeshard-ut_auditsettings + TEST_ARG + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + LABELS + MEDIUM +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + PROCESSORS + 1 +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + TIMEOUT + 60 +) +target_allocator(ydb-core-tx-schemeshard-ut_auditsettings + cpp-malloc-jemalloc +) +vcs_info(ydb-core-tx-schemeshard-ut_auditsettings) diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-x86_64.txt b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-x86_64.txt new file mode 100644 index 0000000000..b152b4143d --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.linux-x86_64.txt @@ -0,0 +1,88 @@ + +# This file was generated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_executable(ydb-core-tx-schemeshard-ut_auditsettings) +target_compile_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard +) +target_link_libraries(ydb-core-tx-schemeshard-ut_auditsettings PUBLIC + contrib-libs-linux-headers + contrib-libs-cxxsupp + yutil + library-cpp-cpuid_check + cpp-testing-unittest_main + core-tx-schemeshard + library-cpp-getopt + cpp-regex-pcre + library-cpp-svnversion + core-testlib-default + ydb-core-tx + tx-schemeshard-ut_helpers +) +target_link_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -ldl + -lrt + -Wl,--no-as-needed + -fPIC + -fPIC + -lpthread + -lrt + -ldl +) +target_sources(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp +) +set_property( + TARGET + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + SPLIT_FACTOR + 10 +) +add_yunittest( + NAME + ydb-core-tx-schemeshard-ut_auditsettings + TEST_TARGET + ydb-core-tx-schemeshard-ut_auditsettings + TEST_ARG + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + LABELS + MEDIUM +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + PROCESSORS + 1 +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + TIMEOUT + 60 +) +target_allocator(ydb-core-tx-schemeshard-ut_auditsettings + cpp-malloc-tcmalloc + libs-tcmalloc-no_percpu_cache +) +vcs_info(ydb-core-tx-schemeshard-ut_auditsettings) diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.txt b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.txt new file mode 100644 index 0000000000..f8b31df0c1 --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.txt @@ -0,0 +1,17 @@ + +# This file was generated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + +if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA) + include(CMakeLists.linux-aarch64.txt) +elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + include(CMakeLists.darwin-x86_64.txt) +elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA) + include(CMakeLists.windows-x86_64.txt) +elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA) + include(CMakeLists.linux-x86_64.txt) +endif() diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.windows-x86_64.txt b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.windows-x86_64.txt new file mode 100644 index 0000000000..deae92b8dd --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/CMakeLists.windows-x86_64.txt @@ -0,0 +1,76 @@ + +# This file was generated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_executable(ydb-core-tx-schemeshard-ut_auditsettings) +target_compile_options(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard +) +target_link_libraries(ydb-core-tx-schemeshard-ut_auditsettings PUBLIC + contrib-libs-cxxsupp + yutil + library-cpp-cpuid_check + cpp-testing-unittest_main + core-tx-schemeshard + library-cpp-getopt + cpp-regex-pcre + library-cpp-svnversion + core-testlib-default + ydb-core-tx + tx-schemeshard-ut_helpers +) +target_sources(ydb-core-tx-schemeshard-ut_auditsettings PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp +) +set_property( + TARGET + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + SPLIT_FACTOR + 10 +) +add_yunittest( + NAME + ydb-core-tx-schemeshard-ut_auditsettings + TEST_TARGET + ydb-core-tx-schemeshard-ut_auditsettings + TEST_ARG + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + LABELS + MEDIUM +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + PROCESSORS + 1 +) +set_yunittest_property( + TEST + ydb-core-tx-schemeshard-ut_auditsettings + PROPERTY + TIMEOUT + 60 +) +target_allocator(ydb-core-tx-schemeshard-ut_auditsettings + system_allocator +) +vcs_info(ydb-core-tx-schemeshard-ut_auditsettings) diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp b/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp new file mode 100644 index 0000000000..ec1ac722a5 --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/ut_auditsettings.cpp @@ -0,0 +1,344 @@ +#include <ydb/core/tx/schemeshard/ut_helpers/helpers.h> + +using namespace NKikimr; +using namespace NSchemeShard; +using namespace NSchemeShardUT_Private; + +namespace { + +template <class T> +T MessageFromText(const TString& text) { + T msg; + UNIT_ASSERT_C(google::protobuf::TextFormat::ParseFromString(text, &msg), "Invalid protobuf message text"); + return msg; +} + +bool AuditSettingsCompare(TString* diff, const NKikimrSubDomains::TAuditSettings& a, const NKikimrSubDomains::TAuditSettings& b) { + google::protobuf::util::MessageDifferencer d; + d.ReportDifferencesToString(diff); + d.TreatAsSet(NKikimrSubDomains::TAuditSettings::GetDescriptor()->FindFieldByName("ExpectedSubjects")); + return d.Compare(a, b); +} + +} // anonymous namespace + +Y_UNIT_TEST_SUITE(TSchemeShardAuditSettings) { + + const std::vector<TString> CreateTestParams = { + R"()", + R"(AuditSettings { EnableDmlAudit: false })", + R"(AuditSettings { EnableDmlAudit: true })", + R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "A"] })", + }; + + Y_UNIT_TEST(CreateExtSubdomain) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + auto test = [&](const TStringBuf& auditSettingsFragment, const NKikimrSubDomains::TAuditSettings& expected) { + TestCreateExtSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + auditSettingsFragment + )); + env.TestWaitNotification(runtime, txId); + + auto actual = DescribePath(runtime, "/MyRoot/USER_0") + .GetPathDescription() + .GetDomainDescription() + .GetAuditSettings() + ; + + TString diff; + UNIT_ASSERT_C(AuditSettingsCompare(&diff, expected, actual), "FAILED for '" << auditSettingsFragment << "': " << diff); + + TestForceDropExtSubDomain(runtime, ++txId, "/MyRoot", "USER_0"); + env.TestWaitNotification(runtime, txId); + }; + + // for all variations expect returned TAuditSettings equal (or equivalent) to the original input + for (const auto& i : CreateTestParams) { + Cerr << "TEST CreateExtSubdomain, '" << i << "'" << Endl; + test(i, MessageFromText<NKikimrSubDomains::TDomainDescription>(i).GetAuditSettings()); + } + } + + Y_UNIT_TEST(CreateSubdomain) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + auto test = [&](const TStringBuf& auditSettingsFragment, const NKikimrSubDomains::TAuditSettings& expected) { + TestCreateSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + auditSettingsFragment + )); + env.TestWaitNotification(runtime, txId); + + auto actual = DescribePath(runtime, "/MyRoot/USER_0") + .GetPathDescription() + .GetDomainDescription() + .GetAuditSettings() + ; + + TString diff; + UNIT_ASSERT_C(AuditSettingsCompare(&diff, expected, actual), "FAILED for '" << auditSettingsFragment << "': " << diff); + + TestForceDropSubDomain(runtime, ++txId, "/MyRoot", "USER_0"); + env.TestWaitNotification(runtime, txId); + }; + + // for all variations expect returned TAuditSettings equal (or equivalent) to the original input + for (const auto& i : CreateTestParams) { + Cerr << "TEST CreateSubdomain, '" << i << "'" << Endl; + test(i, MessageFromText<NKikimrSubDomains::TDomainDescription>(i).GetAuditSettings()); + } + } + + struct TAlterTestParam { + TString AtCreate; + TString AtAlter; + TString Expected; + }; + std::vector<TAlterTestParam> AlterTestParams = { + // Alter can set AuditSettings + { + .AtCreate = R"()", + .AtAlter = R"()", + .Expected = R"()", + }, + { + .AtCreate = R"()", + .AtAlter = R"(AuditSettings { EnableDmlAudit: false })", + .Expected = R"(AuditSettings { EnableDmlAudit: false })", + }, + { + .AtCreate = R"()", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true })", + .Expected = R"(AuditSettings { EnableDmlAudit: true })", + }, + { + .AtCreate = R"()", + .AtAlter = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"()", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"()", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "A"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "A"] })", + }, + // Alter doesn't drop existing AuditSettings + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false })", + .AtAlter = R"()", + .Expected = R"(AuditSettings { EnableDmlAudit: false })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true })", + .AtAlter = R"()", + .Expected = R"(AuditSettings { EnableDmlAudit: true })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"()", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"()", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + }, + // EnableDmlAudit changes independently of ExpectedSubjects + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false })", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true })", + .Expected = R"(AuditSettings { EnableDmlAudit: true })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true })", + .AtAlter = R"(AuditSettings { EnableDmlAudit: false })", + .Expected = R"(AuditSettings { EnableDmlAudit: false })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { EnableDmlAudit: false })", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + }, + // ExpectedSubjects can be added independently of EnableDmlAudit + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + }, + // ExpectedSubjects can be removed independently of EnableDmlAudit + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: [""] })", + .Expected = R"(AuditSettings { EnableDmlAudit: false })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: [""] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true })", + }, + // ExpectedSubjects can be changed independently of EnableDmlAudit + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + }, + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["A", "B"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["A", "B"] })", + }, + // Empty subjects are removed + { + .AtCreate = R"(AuditSettings { ExpectedSubjects: ["A"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["", "B"] })", + .Expected = R"(AuditSettings { ExpectedSubjects: ["B"] })", + }, + { + .AtCreate = R"(AuditSettings { ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { ExpectedSubjects: ["", "", "C", ""] })", + .Expected = R"(AuditSettings { ExpectedSubjects: ["C"] })", + }, + // EnableDmlAudit and ExpectedSubjects could be changed both + { + .AtCreate = R"(AuditSettings { EnableDmlAudit: false ExpectedSubjects: ["A", "B"] })", + .AtAlter = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["C", "D"] })", + .Expected = R"(AuditSettings { EnableDmlAudit: true ExpectedSubjects: ["C", "D"] })", + }, + }; + + Y_UNIT_TEST_FLAG(AlterExtSubdomain, ExternalSchemeShard) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + TString externalSchemeshard; + if (ExternalSchemeShard) { + externalSchemeshard = R"( + ExternalSchemeShard: true + PlanResolution: 50 + Coordinators: 1 + Mediators: 1 + TimeCastBucketsPerMediator: 2 + StoragePools { + Name: "pool-1" + Kind: "hdd" + } + )"; + } + + auto test = [&](const TStringBuf& atCreate, const TStringBuf& atAlter, const NKikimrSubDomains::TAuditSettings& expected) { + TestCreateExtSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + atCreate + )); + TestAlterExtSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + externalSchemeshard, + atAlter + )); + env.TestWaitNotification(runtime, {txId, txId - 1}); + + const auto& describe = DescribePath(runtime, "/MyRoot/USER_0"); + + auto actual = describe.GetPathDescription().GetDomainDescription().GetAuditSettings(); + TString diff; + UNIT_ASSERT_C(AuditSettingsCompare(&diff, expected, actual), "(at root) FAILED for '" << atCreate << "' + '" << atAlter << "': " << diff); + + if (ExternalSchemeShard) { + // check auditSettings at tenant schemeshard also + ui64 tenantSchemeShard = describe.GetPathDescription().GetDomainDescription().GetProcessingParams().GetSchemeShard(); + const auto& describe = DescribePath(runtime, tenantSchemeShard, "/MyRoot/USER_0"); + + auto actual = describe.GetPathDescription().GetDomainDescription().GetAuditSettings(); + TString diff; + UNIT_ASSERT_C(AuditSettingsCompare(&diff, expected, actual), "(at tenant) FAILED for '" << atCreate << "' + '" << atAlter << "': " << diff); + } + + TestForceDropExtSubDomain(runtime, ++txId, "/MyRoot", "USER_0"); + env.TestWaitNotification(runtime, txId); + }; + + // for all variations match actual returned TAuditSettings to expected + for (const auto& [atCreate, atAlter, expected] : AlterTestParams) { + Cerr << "TEST AlterExtSubdomain, '" << atCreate << "' + '" << atAlter << "'" << Endl; + test(atCreate, atAlter, MessageFromText<NKikimrSubDomains::TDomainDescription>(expected).GetAuditSettings()); + } + } + + Y_UNIT_TEST(AlterSubdomain) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + auto test = [&](const TStringBuf& atCreate, const TStringBuf& atAlter, const NKikimrSubDomains::TAuditSettings& expected) { + TestCreateSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + atCreate + )); + TestAlterSubDomain(runtime, ++txId, "/MyRoot", TString::Join( + R"( + Name: "USER_0" + )", + atAlter + )); + env.TestWaitNotification(runtime, {txId, txId - 1}); + + const auto& describe = DescribePath(runtime, "/MyRoot/USER_0"); + + auto actual = describe.GetPathDescription().GetDomainDescription().GetAuditSettings(); + TString diff; + UNIT_ASSERT_C(AuditSettingsCompare(&diff, expected, actual), "(at root) FAILED for '" << atCreate << "' + '" << atAlter << "': " << diff); + + TestForceDropSubDomain(runtime, ++txId, "/MyRoot", "USER_0"); + env.TestWaitNotification(runtime, txId); + }; + + // for all variations match actual returned TAuditSettings to expected + for (const auto& [atCreate, atAlter, expected] : AlterTestParams) { + Cerr << "TEST AlterSubdomain, '" << atCreate << "' + '" << atAlter << "'" << Endl; + test(atCreate, atAlter, MessageFromText<NKikimrSubDomains::TDomainDescription>(expected).GetAuditSettings()); + } + } +} diff --git a/ydb/core/tx/schemeshard/ut_auditsettings/ya.make b/ydb/core/tx/schemeshard/ut_auditsettings/ya.make new file mode 100644 index 0000000000..3136e829b4 --- /dev/null +++ b/ydb/core/tx/schemeshard/ut_auditsettings/ya.make @@ -0,0 +1,30 @@ +UNITTEST_FOR(ydb/core/tx/schemeshard) + +FORK_SUBTESTS() + +IF (SANITIZER_TYPE OR WITH_VALGRIND) + TIMEOUT(3600) + SIZE(LARGE) + TAG(ya:fat) +ELSE() + TIMEOUT(60) + SIZE(MEDIUM) +ENDIF() + +PEERDIR( + library/cpp/getopt + library/cpp/regex/pcre + library/cpp/svnversion + ydb/core/testlib/default + ydb/core/tx + ydb/core/tx/schemeshard/ut_helpers + # ydb/library/yql/public/udf/service/exception_policy +) + +YQL_LAST_ABI_VERSION() + +SRCS( + ut_auditsettings.cpp +) + +END() diff --git a/ydb/core/tx/schemeshard/ut_extsubdomain/ut_extsubdomain.cpp b/ydb/core/tx/schemeshard/ut_extsubdomain/ut_extsubdomain.cpp index 2fe6db2a71..bf39bfe9cc 100644 --- a/ydb/core/tx/schemeshard/ut_extsubdomain/ut_extsubdomain.cpp +++ b/ydb/core/tx/schemeshard/ut_extsubdomain/ut_extsubdomain.cpp @@ -1489,4 +1489,4 @@ Y_UNIT_TEST_SUITE(TSchemeShardExtSubDomainTest) { KeyColumnNames: ["key"] )", {NKikimrScheme::StatusQuotaExceeded}); } -} +}
\ No newline at end of file diff --git a/ydb/core/tx/schemeshard/ya.make b/ydb/core/tx/schemeshard/ya.make index 5f662cdef4..1240b5ce21 100644 --- a/ydb/core/tx/schemeshard/ya.make +++ b/ydb/core/tx/schemeshard/ya.make @@ -1,4 +1,5 @@ RECURSE_FOR_TESTS( + ut_auditsettings ut_backup ut_base ut_base_reboots diff --git a/ydb/tests/functional/scheme_tests/canondata/tablet_scheme_tests.TestTabletSchemes.test_tablet_schemes_flat_schemeshard_/flat_schemeshard.schema b/ydb/tests/functional/scheme_tests/canondata/tablet_scheme_tests.TestTabletSchemes.test_tablet_schemes_flat_schemeshard_/flat_schemeshard.schema index e67b0083cd..94b09951bf 100644 --- a/ydb/tests/functional/scheme_tests/canondata/tablet_scheme_tests.TestTabletSchemes.test_tablet_schemes_flat_schemeshard_/flat_schemeshard.schema +++ b/ydb/tests/functional/scheme_tests/canondata/tablet_scheme_tests.TestTabletSchemes.test_tablet_schemes_flat_schemeshard_/flat_schemeshard.schema @@ -1265,11 +1265,6 @@ ], "ColumnsAdded": [ { - "ColumnId": 29, - "ColumnName": "ImportsLimit", - "ColumnType": "Uint64" - }, - { "ColumnId": 1, "ColumnName": "PathId", "ColumnType": "Uint64" @@ -1408,13 +1403,22 @@ "ColumnId": 28, "ColumnName": "ExportsLimit", "ColumnType": "Uint64" + }, + { + "ColumnId": 29, + "ColumnName": "ImportsLimit", + "ColumnType": "Uint64" + }, + { + "ColumnId": 30, + "ColumnName": "AuditSettings", + "ColumnType": "String" } ], "ColumnsDropped": [], "ColumnFamilies": { "0": { "Columns": [ - 29, 1, 2, 3, @@ -1442,7 +1446,9 @@ 25, 26, 27, - 28 + 28, + 29, + 30 ], "RoomID": 0, "Codec": 0, @@ -2153,6 +2159,11 @@ "ColumnId": 9, "ColumnName": "DatabaseQuotas", "ColumnType": "String" + }, + { + "ColumnId": 10, + "ColumnName": "AuditSettings", + "ColumnType": "String" } ], "ColumnsDropped": [], @@ -2167,7 +2178,8 @@ 6, 7, 8, - 9 + 9, + 10 ], "RoomID": 0, "Codec": 0, |