diff options
author | Nikita Vasilev <ns-vasilev@ydb.tech> | 2025-07-02 12:23:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-02 12:23:12 +0300 |
commit | 9f38b92a88a1f58076febab540e14a74dda18b56 (patch) | |
tree | 13309282185518f0009af6ad3c79ea4a3c52efcc | |
parent | f0176285cf0af5c49d3d5ea352d57352bfa02751 (diff) | |
download | ydb-9f38b92a88a1f58076febab540e14a74dda18b56.tar.gz |
Fix ACL for temp tables (#20444)
-rw-r--r-- | ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp | 35 | ||||
-rw-r--r-- | ydb/core/kqp/ut/scheme/kqp_acl_ut.cpp | 274 | ||||
-rw-r--r-- | ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp | 14 |
3 files changed, 299 insertions, 24 deletions
diff --git a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp index 0f8f3d2b8c7..5c310673fde 100644 --- a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp +++ b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp @@ -114,15 +114,6 @@ public: auto* makeDir = modifyScheme->MutableMkDir(); makeDir->SetName(GetSessionDirName()); - NACLib::TDiffACL diffAcl; - diffAcl.AddAccess( - NACLib::EAccessType::Allow, - NACLib::EAccessRights::CreateDirectory | NACLib::EAccessRights::DescribeSchema, - AppData()->AllAuthenticatedUsers); - - auto* modifyAcl = modifyScheme->MutableModifyACL(); - modifyAcl->SetDiffACL(diffAcl.SerializeAsString()); - auto promise = NewPromise<IKqpGateway::TGenericResult>(); IActor* requestHandler = new TSchemeOpRequestHandler(ev.Release(), promise, false); RegisterWithSameMailbox(requestHandler); @@ -142,9 +133,7 @@ public: auto& record = ev->Record; record.SetDatabaseName(Database); - if (UserToken) { - record.SetUserToken(UserToken->GetSerializedToken()); - } + record.SetUserToken(NACLib::TSystemUsers::Tmp().SerializeAsString()); record.SetPeerName(ClientAddress); auto* modifyScheme = record.MutableTransaction()->MutableModifyScheme(); @@ -156,14 +145,20 @@ public: makeDir->SetName(SessionId); ActorIdToProto(KqpTempTablesAgentActor, modifyScheme->MutableTempDirOwnerActorId()); - NACLib::TDiffACL diffAcl; - diffAcl.RemoveAccess( - NACLib::EAccessType::Allow, - NACLib::EAccessRights::CreateDirectory | NACLib::EAccessRights::DescribeSchema, - AppData()->AllAuthenticatedUsers); - - auto* modifyAcl = modifyScheme->MutableModifyACL(); - modifyAcl->SetDiffACL(diffAcl.SerializeAsString()); + if (UserToken) { + constexpr ui32 access = NACLib::EAccessRights::CreateDirectory + | NACLib::EAccessRights::CreateTable + | NACLib::EAccessRights::RemoveSchema + | NACLib::EAccessRights::DescribeSchema; + + NACLib::TDiffACL diffAcl; + diffAcl.AddAccess( + NACLib::EAccessType::Allow, + access, + UserToken->GetUserSID()); + auto* modifyAcl = modifyScheme->MutableModifyACL(); + modifyAcl->SetDiffACL(diffAcl.SerializeAsString()); + } auto promise = NewPromise<IKqpGateway::TGenericResult>(); IActor* requestHandler = new TSchemeOpRequestHandler(ev.Release(), promise, false); diff --git a/ydb/core/kqp/ut/scheme/kqp_acl_ut.cpp b/ydb/core/kqp/ut/scheme/kqp_acl_ut.cpp index 85960f3810c..27f7ebebcff 100644 --- a/ydb/core/kqp/ut/scheme/kqp_acl_ut.cpp +++ b/ydb/core/kqp/ut/scheme/kqp_acl_ut.cpp @@ -774,6 +774,280 @@ Y_UNIT_TEST_SUITE(KqpAcl) { } } } + + Y_UNIT_TEST_QUAD(AclTemporary, IsOlap, UseAdmin) { + NKikimrConfig::TAppConfig appConfig; + appConfig.MutableTableServiceConfig()->SetEnableOltpSink(true); + appConfig.MutableTableServiceConfig()->SetEnableOlapSink(true); + auto settings = NKqp::TKikimrSettings() + .SetAppConfig(appConfig) + .SetWithSampleTables(false) + .SetEnableTempTables(true); + TKikimrRunner kikimr(settings); + if (UseAdmin) { + kikimr.GetTestClient().GrantConnect("user_write@builtin"); + kikimr.GetTestServer().GetRuntime()->GetAppData().AdministrationAllowedSIDs.emplace_back("root@builtin"); + } + + const TString UserWriteName = "user_write@builtin"; + const TString UserReadName = "root@builtin"; + + auto driverWriteConfig = TDriverConfig() + .SetEndpoint(kikimr.GetEndpoint()) + .SetAuthToken(UserWriteName) + .SetDatabase("/Root"); + auto driverWrite = TDriver(driverWriteConfig); + auto clientWrite = NYdb::NQuery::TQueryClient(driverWrite); + + auto sessionWrite = CreateSession(clientWrite); + auto sessionWriteOther = CreateSession(clientWrite); + + auto driverReadConfig = TDriverConfig() + .SetEndpoint(kikimr.GetEndpoint()) + .SetAuthToken(UserReadName) + .SetDatabase("/Root"); + auto driverRead = TDriver(driverReadConfig); + auto clientRead = NYdb::NQuery::TQueryClient(driverRead); + + auto sessionRead = CreateSession(clientRead); + + + { + const TString queryWrite = Sprintf(R"( + CREATE TEMPORARY TABLE `/Root/Test` ( + id Uint64 NOT NULL, + name String, + primary key (id) + ) WITH (STORE=%s); + )", IsOlap ? "COLUMN" : "ROW"); + + auto result = sessionWrite.ExecuteQuery(queryWrite, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + // tmp table by session alias + const TString queryWithAlias = R"( + UPSERT INTO `/Root/Test` (id, name) VALUES + (10u, "One"); + )"; + + { + auto result = sessionWrite.ExecuteQuery(queryWithAlias, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + { + auto result = sessionWriteOther.ExecuteQuery(queryWithAlias, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString()); + } + + { + auto result = sessionRead.ExecuteQuery(queryWithAlias, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString()); + } + + // tmp table by real path + const TStringBuf sessionPrefix = "&id="; + const auto pos = sessionWrite.GetId().find(sessionPrefix); + + const TString sessionTmpDir = TStringBuilder() + << "/Root/.tmp/sessions/" + << sessionWrite.GetId().substr(pos + sessionPrefix.size()); + + { + auto result = sessionWrite.ExecuteQuery(Sprintf(R"( + CREATE TABLE `%s/Test` ( + id Uint64 NOT NULL, + name String, + primary key (id) + ); + )", sessionTmpDir.c_str()), NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + + UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString()); + UNIT_ASSERT_C(result.GetIssues().ToString().contains("path is temporary"), result.GetIssues().ToString()); + } + + const TString queryWithRealPath = Sprintf(R"( + UPSERT INTO `%s/Root/Test` (id, name) VALUES + (10u, "One"); + )", sessionTmpDir.c_str()); + + const TString queryWithFakePath = Sprintf(R"( + UPSERT INTO `%s/Root/Test2` (id, name) VALUES + (10u, "One"); + )", sessionTmpDir.c_str()); + + { + auto result = sessionWrite.ExecuteQuery(queryWithRealPath, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + { + auto result = sessionWriteOther.ExecuteQuery(queryWithRealPath, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + { + auto result = sessionRead.ExecuteQuery(queryWithRealPath, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + + UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString()); + UNIT_ASSERT_C(result.GetIssues().ToString().contains("because it does not exist or you do not have access permissions. Please check correctness of table path and user permissions."), result.GetIssues().ToString()); + } + + { + auto result = sessionRead.ExecuteQuery(queryWithFakePath, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); + + UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString()); + UNIT_ASSERT_C(result.GetIssues().ToString().contains("because it does not exist or you do not have access permissions. Please check correctness of table path and user permissions."), result.GetIssues().ToString()); + } + + auto schemeClientWrite = NYdb::NScheme::TSchemeClient(driverWrite); + auto schemeClientRead = NYdb::NScheme::TSchemeClient(driverRead); + + { + auto result = schemeClientWrite.ListDirectory(sessionTmpDir).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + { + auto result = schemeClientRead.ListDirectory(sessionTmpDir).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.DescribePath(sessionTmpDir).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + { + auto result = schemeClientRead.DescribePath(sessionTmpDir).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.ListDirectory("/Root/.tmp").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.ListDirectory("/Root/.tmp").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.DescribePath("/Root/.tmp").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.DescribePath("/Root/.tmp").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.ListDirectory("/Root/.tmp/sessions").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.ListDirectory("/Root/.tmp/sessions").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.DescribePath("/Root/.tmp/sessions").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.DescribePath("/Root/.tmp/sessions").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + + { + auto result = schemeClientWrite.MakeDirectory("/Root/.tmp/test1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.MakeDirectory("/Root/.tmp/test2").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.MakeDirectory("/Root/.tmp/sessions/test1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.MakeDirectory("/Root/.tmp/sessions/test2").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientWrite.MakeDirectory(sessionTmpDir + "/test1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::PRECONDITION_FAILED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "path is temporary", + result.GetIssues().ToString() + ); + } + + { + auto result = schemeClientRead.MakeDirectory(sessionTmpDir + "/test2").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::UNAUTHORIZED); + UNIT_ASSERT_STRING_CONTAINS_C(result.GetIssues().ToString(), "Access denied", + result.GetIssues().ToString() + ); + } + + driverWrite.Stop(true); + driverRead.Stop(true); + } } } // namespace NKqp diff --git a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp index d4ccfb5f94d..08b2c5da857 100644 --- a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp +++ b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp @@ -1908,6 +1908,8 @@ Y_UNIT_TEST_SUITE(KqpQueryService) { serverSettings.SetWithSampleTables(false).SetEnableTempTables(true)); auto clientConfig = NGRpcProxy::TGRpcClientConfig(kikimr.GetEndpoint()); auto client = kikimr.GetQueryClient(); + + TString SessionId; { auto session = client.GetSession().GetValueSync().GetSession(); auto id = session.GetId(); @@ -1933,13 +1935,15 @@ Y_UNIT_TEST_SUITE(KqpQueryService) { UNIT_ASSERT_C(resultSelect.IsSuccess(), resultSelect.GetIssues().ToString()); const TVector<TString> sessionIdSplitted = StringSplitter(id).SplitByString("&id="); + SessionId = sessionIdSplitted.back(); + const auto queryCreateRestricted = Q_(fmt::format(R"( --!syntax_v1 CREATE TABLE `/Root/.tmp/sessions/{}/Test` ( Key Uint64 NOT NULL, Value String, PRIMARY KEY (Key) - );)", sessionIdSplitted.back())); + );)", SessionId)); auto resultCreateRestricted = session.ExecuteQuery(queryCreateRestricted, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync(); UNIT_ASSERT(!resultCreateRestricted.IsSuccess()); @@ -1966,9 +1970,11 @@ Y_UNIT_TEST_SUITE(KqpQueryService) { { auto schemeClient = kikimr.GetSchemeClient(); - auto listResult = schemeClient.ListDirectory("/Root/.tmp/sessions").GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL_C(listResult.GetStatus(), NYdb::EStatus::SUCCESS, listResult.GetIssues().ToString()); - UNIT_ASSERT_VALUES_EQUAL(listResult.GetChildren().size(), 0); + auto listResult = schemeClient.ListDirectory( + fmt::format("/Root/.tmp/sessions/{}", SessionId) + ).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(listResult.GetStatus(), NYdb::EStatus::SCHEME_ERROR, listResult.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS_C(listResult.GetIssues().ToString(), "Path not found",listResult.GetIssues().ToString()); } } |