diff options
author | ivanmorozov <ivanmorozov@yandex-team.com> | 2022-12-06 19:02:49 +0300 |
---|---|---|
committer | ivanmorozov <ivanmorozov@yandex-team.com> | 2022-12-06 19:02:49 +0300 |
commit | 2ee1b39019d2e6e4faf3fb0e271f1a0015fe597b (patch) | |
tree | 20d971a42f8753599c38e2eab0a0cd894f8d8936 | |
parent | 9e86f008b433b72167dd572b43d57bd5e86479fa (diff) | |
download | ydb-2ee1b39019d2e6e4faf3fb0e271f1a0015fe597b.tar.gz |
add validation for secret operations
add test
-rw-r--r-- | ydb/core/testlib/common_helper.cpp | 2 | ||||
-rw-r--r-- | ydb/services/metadata/secret/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ydb/services/metadata/secret/access.cpp | 19 | ||||
-rw-r--r-- | ydb/services/metadata/secret/access.h | 13 | ||||
-rw-r--r-- | ydb/services/metadata/secret/checker_access.cpp | 50 | ||||
-rw-r--r-- | ydb/services/metadata/secret/checker_access.h | 35 | ||||
-rw-r--r-- | ydb/services/metadata/secret/checker_secret.cpp | 51 | ||||
-rw-r--r-- | ydb/services/metadata/secret/checker_secret.h | 35 | ||||
-rw-r--r-- | ydb/services/metadata/secret/initializer.cpp | 4 | ||||
-rw-r--r-- | ydb/services/metadata/secret/secret.cpp | 18 | ||||
-rw-r--r-- | ydb/services/metadata/secret/secret.h | 3 | ||||
-rw-r--r-- | ydb/services/metadata/secret/snapshot.cpp | 7 | ||||
-rw-r--r-- | ydb/services/metadata/secret/ut/ut_secret.cpp | 49 |
13 files changed, 265 insertions, 23 deletions
diff --git a/ydb/core/testlib/common_helper.cpp b/ydb/core/testlib/common_helper.cpp index 20e271c734..5c780b0ba7 100644 --- a/ydb/core/testlib/common_helper.cpp +++ b/ydb/core/testlib/common_helper.cpp @@ -50,7 +50,7 @@ void THelper::StartSchemaRequest(const TString& request, const bool expectSucces TStringStream ss; f.GetValueSync().GetIssues().PrintTo(ss, false); Cerr << ss.Str() << Endl; - Y_VERIFY(expectation == f.GetValueSync().IsSuccess()); + Y_VERIFY(expectation == f.GetValueSync().IsSuccess(), "%d", expectation ? 1 : 0); *rrPtr = true; }); }); diff --git a/ydb/services/metadata/secret/CMakeLists.txt b/ydb/services/metadata/secret/CMakeLists.txt index d941a689b4..fb14fafd17 100644 --- a/ydb/services/metadata/secret/CMakeLists.txt +++ b/ydb/services/metadata/secret/CMakeLists.txt @@ -25,6 +25,8 @@ target_sources(services-metadata-secret PRIVATE ${CMAKE_SOURCE_DIR}/ydb/services/metadata/secret/snapshot.cpp ${CMAKE_SOURCE_DIR}/ydb/services/metadata/secret/initializer.cpp ${CMAKE_SOURCE_DIR}/ydb/services/metadata/secret/fetcher.cpp + ${CMAKE_SOURCE_DIR}/ydb/services/metadata/secret/checker_secret.cpp + ${CMAKE_SOURCE_DIR}/ydb/services/metadata/secret/checker_access.cpp ) add_global_library_for(services-metadata-secret.global services-metadata-secret) diff --git a/ydb/services/metadata/secret/access.cpp b/ydb/services/metadata/secret/access.cpp index 3d25812f03..96cb981d08 100644 --- a/ydb/services/metadata/secret/access.cpp +++ b/ydb/services/metadata/secret/access.cpp @@ -1,4 +1,5 @@ #include "access.h" +#include "checker_access.h" #include <ydb/core/base/appdata.h> #include <ydb/services/metadata/manager/ydb_value_operator.h> @@ -15,7 +16,7 @@ bool TAccess::DeserializeFromRecord(const TDecoder& decoder, const Ydb::Value& r if (!decoder.Read(decoder.GetSecretIdIdx(), SecretId, rawValue)) { return false; } - if (!decoder.Read(decoder.GetAccessUserIdIdx(), AccessUserId, rawValue)) { + if (!decoder.Read(decoder.GetAccessSIDIdx(), AccessSID, rawValue)) { return false; } return true; @@ -25,13 +26,17 @@ NMetadataManager::TTableRecord TAccess::SerializeToRecord() const { NMetadataManager::TTableRecord result; result.SetColumn(TDecoder::OwnerUserId, NMetadataManager::TYDBValue::Bytes(OwnerUserId)); result.SetColumn(TDecoder::SecretId, NMetadataManager::TYDBValue::Bytes(SecretId)); - result.SetColumn(TDecoder::AccessUserId, NMetadataManager::TYDBValue::Bytes(AccessUserId)); + result.SetColumn(TDecoder::AccessSID, NMetadataManager::TYDBValue::Bytes(AccessSID)); return result; } void TAccess::AlteringPreparation(std::vector<TAccess>&& objects, NMetadataManager::IAlterPreparationController<TAccess>::TPtr controller, const NMetadata::IOperationsManager::TModificationContext& context) { + if (context.GetActivityType() == IOperationsManager::EActivityType::Alter) { + controller->PreparationProblem("access object cannot be modified"); + return; + } if (!!context.GetUserToken()) { for (auto&& i : objects) { if (i.GetOwnerUserId() != context.GetUserToken()->GetUserSID()) { @@ -40,7 +45,7 @@ void TAccess::AlteringPreparation(std::vector<TAccess>&& objects, } } } - controller->PreparationFinished(std::move(objects)); + TActivationContext::Register(new TAccessPreparationActor(std::move(objects), controller, context)); } NMetadata::TOperationParsingResult TAccess::BuildPatchFromSettings(const NYql::TObjectSettingsImpl& settings, @@ -51,10 +56,10 @@ NMetadata::TOperationParsingResult TAccess::BuildPatchFromSettings(const NYql::T TStringBuf l; TStringBuf r; if (!sb.TrySplit(':', l, r)) { - return "incorrect objectId format (secretId:accessUserId)"; + return "incorrect objectId format (secretId:accessSID)"; } result.SetColumn(TDecoder::SecretId, NMetadataManager::TYDBValue::Bytes(l)); - result.SetColumn(TDecoder::AccessUserId, NMetadataManager::TYDBValue::Bytes(r)); + result.SetColumn(TDecoder::AccessSID, NMetadataManager::TYDBValue::Bytes(r)); if (!context.GetUserToken()) { auto it = settings.GetFeatures().find(TDecoder::OwnerUserId); if (it != settings.GetFeatures().end()) { @@ -72,7 +77,7 @@ std::vector<Ydb::Column> TAccess::TDecoder::GetColumns() { return { NMetadataManager::TYDBColumn::Bytes(OwnerUserId), NMetadataManager::TYDBColumn::Bytes(SecretId), - NMetadataManager::TYDBColumn::Bytes(AccessUserId) + NMetadataManager::TYDBColumn::Bytes(AccessSID) }; } @@ -81,7 +86,7 @@ std::vector<Ydb::Column> TAccess::TDecoder::GetPKColumns() { } std::vector<TString> TAccess::TDecoder::GetPKColumnIds() { - return { OwnerUserId, SecretId, AccessUserId }; + return { OwnerUserId, SecretId, AccessSID }; } } diff --git a/ydb/services/metadata/secret/access.h b/ydb/services/metadata/secret/access.h index fd26c20776..7d2d882a49 100644 --- a/ydb/services/metadata/secret/access.h +++ b/ydb/services/metadata/secret/access.h @@ -6,25 +6,24 @@ #include <ydb/services/metadata/abstract/manager.h> #include <ydb/services/metadata/manager/object.h> #include <ydb/services/metadata/manager/preparation_controller.h> +#include <ydb/services/metadata/secret/secret.h> namespace NKikimr::NMetadata::NSecret { -class TAccess: public NMetadataManager::TObject<TAccess> { +class TAccess: public TSecretId, public NMetadataManager::TObject<TAccess> { private: using TBase = NMetadataManager::TObject<TAccess>; - YDB_ACCESSOR_DEF(TString, OwnerUserId); - YDB_ACCESSOR_DEF(TString, SecretId); - YDB_ACCESSOR_DEF(TString, AccessUserId); + YDB_ACCESSOR_DEF(TString, AccessSID); public: class TDecoder: public NInternal::TDecoderBase { private: YDB_ACCESSOR(i32, OwnerUserIdIdx, -1); YDB_ACCESSOR(i32, SecretIdIdx, -1); - YDB_ACCESSOR(i32, AccessUserIdIdx, -1); + YDB_ACCESSOR(i32, AccessSIDIdx, -1); public: static inline const TString OwnerUserId = "ownerUserId"; static inline const TString SecretId = "secretId"; - static inline const TString AccessUserId = "accessUserId"; + static inline const TString AccessSID = "accessSID"; static std::vector<TString> GetPKColumnIds(); static std::vector<Ydb::Column> GetPKColumns(); static std::vector<Ydb::Column> GetColumns(); @@ -32,7 +31,7 @@ public: TDecoder(const Ydb::ResultSet& rawData) { OwnerUserIdIdx = GetFieldIndex(rawData, OwnerUserId); SecretIdIdx = GetFieldIndex(rawData, SecretId); - AccessUserIdIdx = GetFieldIndex(rawData, AccessUserId); + AccessSIDIdx = GetFieldIndex(rawData, AccessSID); } }; diff --git a/ydb/services/metadata/secret/checker_access.cpp b/ydb/services/metadata/secret/checker_access.cpp new file mode 100644 index 0000000000..332d36118e --- /dev/null +++ b/ydb/services/metadata/secret/checker_access.cpp @@ -0,0 +1,50 @@ +#include "checker_access.h" + +#include <ydb/services/metadata/secret/snapshot.h> +#include <ydb/services/metadata/secret/fetcher.h> + +namespace NKikimr::NMetadata::NSecret { + +void TAccessPreparationActor::StartChecker() { + Y_VERIFY(Secrets); + auto g = PassAwayGuard(); + for (auto&& i : Objects) { + if (Context.GetActivityType() == IOperationsManager::EActivityType::Create) { + bool foundSecret = false; + for (auto&& [_, s] : Secrets->GetSecrets()) { + if (s.GetOwnerUserId() == i.GetOwnerUserId() && s.GetSecretId() == i.GetSecretId()) { + foundSecret = true; + break; + } + } + if (!foundSecret) { + Controller->PreparationProblem("used in access secret " + i.GetSecretId() + " not found"); + return; + } + } + } + Controller->PreparationFinished(std::move(Objects)); +} + +void TAccessPreparationActor::Handle(NMetadataProvider::TEvRefreshSubscriberData::TPtr& ev) { + Secrets = ev->Get()->GetValidatedSnapshotAs<NMetadata::NSecret::TSnapshot>(); + StartChecker(); +} + +void TAccessPreparationActor::Bootstrap() { + Become(&TThis::StateMain); + Send(NMetadataProvider::MakeServiceId(SelfId().NodeId()), + new NMetadataProvider::TEvAskSnapshot(std::make_shared<NMetadata::NSecret::TSnapshotsFetcher>())); +} + +TAccessPreparationActor::TAccessPreparationActor(std::vector<TAccess>&& objects, + NMetadataManager::IAlterPreparationController<TAccess>::TPtr controller, + const NMetadata::IOperationsManager::TModificationContext& context) + : Objects(std::move(objects)) + , Controller(controller) + , Context(context) +{ + +} + +} diff --git a/ydb/services/metadata/secret/checker_access.h b/ydb/services/metadata/secret/checker_access.h new file mode 100644 index 0000000000..80f7afece4 --- /dev/null +++ b/ydb/services/metadata/secret/checker_access.h @@ -0,0 +1,35 @@ +#pragma once +#include "access.h" + +#include <ydb/services/metadata/abstract/common.h> +#include <ydb/services/metadata/abstract/kqp_common.h> +#include <ydb/services/metadata/manager/preparation_controller.h> +#include <ydb/services/metadata/secret/snapshot.h> + +namespace NKikimr::NMetadata::NSecret { + +class TAccessPreparationActor: public NActors::TActorBootstrapped<TAccessPreparationActor> { +private: + std::vector<TAccess> Objects; + NMetadataManager::IAlterPreparationController<TAccess>::TPtr Controller; + NMetadata::IOperationsManager::TModificationContext Context; + std::shared_ptr<NMetadata::NSecret::TSnapshot> Secrets; + void StartChecker(); +protected: + void Handle(NMetadataProvider::TEvRefreshSubscriberData::TPtr& ev); +public: + STATEFN(StateMain) { + switch (ev->GetTypeRewrite()) { + hFunc(NMetadataProvider::TEvRefreshSubscriberData, Handle); + default: + break; + } + } + void Bootstrap(); + + TAccessPreparationActor(std::vector<TAccess>&& objects, + NMetadataManager::IAlterPreparationController<TAccess>::TPtr controller, + const NMetadata::IOperationsManager::TModificationContext& context); +}; + +} diff --git a/ydb/services/metadata/secret/checker_secret.cpp b/ydb/services/metadata/secret/checker_secret.cpp new file mode 100644 index 0000000000..4188808c20 --- /dev/null +++ b/ydb/services/metadata/secret/checker_secret.cpp @@ -0,0 +1,51 @@ +#include "checker_secret.h" + +#include <ydb/services/metadata/secret/snapshot.h> +#include <ydb/services/metadata/secret/fetcher.h> + +namespace NKikimr::NMetadata::NSecret { + +void TSecretPreparationActor::StartChecker() { + Y_VERIFY(Secrets); + auto g = PassAwayGuard(); + for (auto&& i : Objects) { + if (Context.GetActivityType() == IOperationsManager::EActivityType::Alter) { + if (!Secrets->GetSecrets().contains(i)) { + Controller->PreparationProblem("secret " + i.GetSecretId() + " not found for alter"); + return; + } + } + for (auto&& sa : Secrets->GetAccess()) { + if (Context.GetActivityType() == IOperationsManager::EActivityType::Drop) { + if (sa.GetOwnerUserId() == i.GetOwnerUserId() && sa.GetSecretId() == i.GetSecretId()) { + Controller->PreparationProblem("secret " + i.GetSecretId() + " using in access for " + sa.GetAccessSID()); + return; + } + } + } + } + Controller->PreparationFinished(std::move(Objects)); +} + +void TSecretPreparationActor::Handle(NMetadataProvider::TEvRefreshSubscriberData::TPtr& ev) { + Secrets = ev->Get()->GetValidatedSnapshotAs<NMetadata::NSecret::TSnapshot>(); + StartChecker(); +} + +void TSecretPreparationActor::Bootstrap() { + Become(&TThis::StateMain); + Send(NMetadataProvider::MakeServiceId(SelfId().NodeId()), + new NMetadataProvider::TEvAskSnapshot(std::make_shared<NMetadata::NSecret::TSnapshotsFetcher>())); +} + +TSecretPreparationActor::TSecretPreparationActor(std::vector<TSecret>&& objects, + NMetadataManager::IAlterPreparationController<TSecret>::TPtr controller, + const NMetadata::IOperationsManager::TModificationContext& context) + : Objects(std::move(objects)) + , Controller(controller) + , Context(context) +{ + +} + +} diff --git a/ydb/services/metadata/secret/checker_secret.h b/ydb/services/metadata/secret/checker_secret.h new file mode 100644 index 0000000000..6b7db5353e --- /dev/null +++ b/ydb/services/metadata/secret/checker_secret.h @@ -0,0 +1,35 @@ +#pragma once + +#include <ydb/services/metadata/abstract/common.h> +#include <ydb/services/metadata/abstract/kqp_common.h> +#include <ydb/services/metadata/manager/preparation_controller.h> +#include <ydb/services/metadata/secret/secret.h> +#include <ydb/services/metadata/secret/snapshot.h> + +namespace NKikimr::NMetadata::NSecret { + +class TSecretPreparationActor: public NActors::TActorBootstrapped<TSecretPreparationActor> { +private: + std::vector<TSecret> Objects; + NMetadataManager::IAlterPreparationController<TSecret>::TPtr Controller; + NMetadata::IOperationsManager::TModificationContext Context; + std::shared_ptr<NMetadata::NSecret::TSnapshot> Secrets; + void StartChecker(); +protected: + void Handle(NMetadataProvider::TEvRefreshSubscriberData::TPtr& ev); +public: + STATEFN(StateMain) { + switch (ev->GetTypeRewrite()) { + hFunc(NMetadataProvider::TEvRefreshSubscriberData, Handle); + default: + break; + } + } + void Bootstrap(); + + TSecretPreparationActor(std::vector<TSecret>&& objects, + NMetadataManager::IAlterPreparationController<TSecret>::TPtr controller, + const NMetadata::IOperationsManager::TModificationContext& context); +}; + +} diff --git a/ydb/services/metadata/secret/initializer.cpp b/ydb/services/metadata/secret/initializer.cpp index cc73a96b5c..6a8cd59af3 100644 --- a/ydb/services/metadata/secret/initializer.cpp +++ b/ydb/services/metadata/secret/initializer.cpp @@ -44,7 +44,7 @@ void TAccessInitializer::DoPrepare(NMetadataInitializer::IInitializerInput::TPtr request.set_path(TAccess::GetStorageTablePath()); request.add_primary_key(TAccess::TDecoder::OwnerUserId); request.add_primary_key(TAccess::TDecoder::SecretId); - request.add_primary_key(TAccess::TDecoder::AccessUserId); + request.add_primary_key(TAccess::TDecoder::AccessSID); { auto& column = *request.add_columns(); column.set_name(TAccess::TDecoder::OwnerUserId); @@ -57,7 +57,7 @@ void TAccessInitializer::DoPrepare(NMetadataInitializer::IInitializerInput::TPtr } { auto& column = *request.add_columns(); - column.set_name(TAccess::TDecoder::AccessUserId); + column.set_name(TAccess::TDecoder::AccessSID); column.mutable_type()->mutable_optional_type()->mutable_item()->set_type_id(Ydb::Type::STRING); } result.emplace_back(new NMetadataInitializer::TGenericTableModifier<NInternal::NRequest::TDialogCreateTable>(request, "create")); diff --git a/ydb/services/metadata/secret/secret.cpp b/ydb/services/metadata/secret/secret.cpp index a7cca08abd..1a203967f0 100644 --- a/ydb/services/metadata/secret/secret.cpp +++ b/ydb/services/metadata/secret/secret.cpp @@ -1,3 +1,4 @@ +#include "checker_secret.h" #include "secret.h" #include <ydb/core/base/appdata.h> #include <ydb/services/metadata/manager/ydb_value_operator.h> @@ -40,7 +41,7 @@ void TSecret::AlteringPreparation(std::vector<TSecret>&& objects, } } } - controller->PreparationFinished(std::move(objects)); + TActivationContext::Register(new TSecretPreparationActor(std::move(objects), controller, context)); } NMetadata::TOperationParsingResult TSecret::BuildPatchFromSettings(const NYql::TObjectSettingsImpl& settings, @@ -56,6 +57,21 @@ NMetadata::TOperationParsingResult TSecret::BuildPatchFromSettings(const NYql::T } else { result.SetColumn(TDecoder::OwnerUserId, NMetadataManager::TYDBValue::Bytes(context.GetUserToken()->GetUserSID())); } + for (auto&& c : settings.GetObjectId()) { + if (c >= '0' && c <= '9') { + continue; + } + if (c >= 'a' && c <= 'z') { + continue; + } + if (c >= 'A' && c <= 'Z') { + continue; + } + if (c == '_') { + continue; + } + return "incorrect character for secret id: '" + TString(c) + "'"; + } { result.SetColumn(TDecoder::SecretId, NMetadataManager::TYDBValue::Bytes(settings.GetObjectId())); } diff --git a/ydb/services/metadata/secret/secret.h b/ydb/services/metadata/secret/secret.h index d000d2829c..07b037522c 100644 --- a/ydb/services/metadata/secret/secret.h +++ b/ydb/services/metadata/secret/secret.h @@ -27,6 +27,9 @@ public: bool operator<(const TSecretId& item) const { return std::tie(OwnerUserId, SecretId) < std::tie(item.OwnerUserId, item.SecretId); } + bool operator==(const TSecretId& item) const { + return std::tie(OwnerUserId, SecretId) == std::tie(item.OwnerUserId, item.SecretId); + } }; class TSecret: public TSecretId, public NMetadataManager::TObject<TSecret> { diff --git a/ydb/services/metadata/secret/snapshot.cpp b/ydb/services/metadata/secret/snapshot.cpp index 13264923a7..7e0b9423e6 100644 --- a/ydb/services/metadata/secret/snapshot.cpp +++ b/ydb/services/metadata/secret/snapshot.cpp @@ -39,7 +39,7 @@ TString TSnapshot::DoSerializeToString() const { } sb << "ACCESS:"; for (auto&& i : Access) { - sb << i.GetOwnerUserId() << ":" << i.GetSecretId() << ":" << i.GetAccessUserId() << ";"; + sb << i.GetOwnerUserId() << ":" << i.GetSecretId() << ":" << i.GetAccessSID() << ";"; } return sb; } @@ -73,7 +73,10 @@ bool TSnapshot::CheckSecretAccess(const TString& secretableString, const std::op return true; } for (auto&& i : Access) { - if (i.GetAccessUserId() == userToken->GetUserSID()) { + if (i != sId) { + continue; + } + if (userToken->IsExist(i.GetAccessSID())) { return true; } } diff --git a/ydb/services/metadata/secret/ut/ut_secret.cpp b/ydb/services/metadata/secret/ut/ut_secret.cpp index 2a17b5e87c..22d4614378 100644 --- a/ydb/services/metadata/secret/ut/ut_secret.cpp +++ b/ydb/services/metadata/secret/ut/ut_secret.cpp @@ -199,9 +199,6 @@ Y_UNIT_TEST_SUITE(Secret) { lHelper.StartSchemaRequest("DROP OBJECT `secret1:test@test1` (TYPE SECRET_ACCESS)"); lHelper.StartSchemaRequest("DROP OBJECT `secret1` (TYPE SECRET)"); lHelper.StartDataRequest("SELECT * FROM `/Root/.metadata/initializations`"); - lHelper.StartSchemaRequest("DELETE FROM `/Root/.metadata/initializations`", false); - lHelper.StartSchemaRequest("DROP TABLE `/Root/.metadata/initializations`", false); - lHelper.StartDataRequest("SELECT * FROM `/Root/.metadata/secrets/values`", false); emulator->SetExpectedSecretsCount(0).SetExpectedAccessCount(0); { @@ -213,5 +210,51 @@ Y_UNIT_TEST_SUITE(Secret) { } } } + + Y_UNIT_TEST(Validation) { + TPortManager pm; + + ui32 grpcPort = pm.GetPort(); + ui32 msgbPort = pm.GetPort(); + + Tests::TServerSettings serverSettings(msgbPort); + serverSettings.Port = msgbPort; + serverSettings.GrpcPort = grpcPort; + serverSettings.SetDomainName("Root") + .SetUseRealThreads(false) + .SetEnableMetadataProvider(true) + .SetEnableOlapSchemaOperations(true); + ; + + Tests::TServer::TPtr server = new Tests::TServer(serverSettings); + server->EnableGRpc(grpcPort); + + Tests::TClient client(serverSettings); + + auto& runtime = *server->GetRuntime(); + + auto sender = runtime.AllocateEdgeActor(); + server->SetupRootStoragePools(sender); + + TSecretUserEmulator* emulator = new TSecretUserEmulator; + runtime.Register(emulator); + { + runtime.SimulateSleep(TDuration::Seconds(10)); + Cerr << "Initialization finished" << Endl; + + Tests::NCS::THelper lHelper(*server); + lHelper.StartSchemaRequest("CREATE OBJECT secret-1 (TYPE SECRET) WITH value = `100`", false); + lHelper.StartSchemaRequest("ALTER OBJECT secret1 (TYPE SECRET) SET value = `abcde`", false); + lHelper.StartSchemaRequest("CREATE OBJECT secret1 (TYPE SECRET) WITH value = `100`"); + lHelper.StartSchemaRequest("ALTER OBJECT secret1 (TYPE SECRET) SET value = `abcde`"); + lHelper.StartSchemaRequest("CREATE OBJECT `secret1:test@test1` (TYPE SECRET_ACCESS)"); + lHelper.StartSchemaRequest("CREATE OBJECT `secret2:test@test1` (TYPE SECRET_ACCESS)", false); + lHelper.StartSchemaRequest("DROP OBJECT `secret1` (TYPE SECRET)", false); + lHelper.StartDataRequest("SELECT * FROM `/Root/.metadata/initializations`"); + lHelper.StartSchemaRequest("DELETE FROM `/Root/.metadata/initializations`", false); + lHelper.StartSchemaRequest("DROP TABLE `/Root/.metadata/initializations`", false); + lHelper.StartDataRequest("SELECT * FROM `/Root/.metadata/secrets/values`", false); + } + } } } |