aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlnaz Nizametdinov <i.nizametdinov@gmail.com>2022-07-04 20:10:43 +0300
committerIlnaz Nizametdinov <i.nizametdinov@gmail.com>2022-07-04 20:10:43 +0300
commit16c46dc5e7e58898f4914b6c133e8d55d14ccd72 (patch)
treed555bcb6ddb4b9d3fb6167ab274f9b630c30f761
parent9253fb8658089f014b3126076642e528d24d8145 (diff)
downloadydb-16c46dc5e7e58898f4914b6c133e8d55d14ccd72.tar.gz
Verify that path belongs to the specified domain KIKIMR-14784
ref:473d2fb21cfa2b65d075cd61dbfd7ef7da233ac2
-rw-r--r--ydb/core/tx/scheme_board/cache.cpp93
-rw-r--r--ydb/core/tx/scheme_board/cache_ut.cpp44
-rw-r--r--ydb/core/tx/scheme_cache/scheme_cache.h2
-rw-r--r--ydb/tests/functional/tenants/test_dynamic_tenants.py2
-rw-r--r--ydb/tests/functional/tenants/test_tenants.py6
5 files changed, 112 insertions, 35 deletions
diff --git a/ydb/core/tx/scheme_board/cache.cpp b/ydb/core/tx/scheme_board/cache.cpp
index da39c00ff0d..321e30b4ccf 100644
--- a/ydb/core/tx/scheme_board/cache.cpp
+++ b/ydb/core/tx/scheme_board/cache.cpp
@@ -161,7 +161,21 @@ namespace {
}
template <typename TContextPtr, typename TEvResult, typename TDerived>
- class TAclChecker: public TActorBootstrapped<TDerived> {
+ class TAccessChecker: public TActorBootstrapped<TDerived> {
+ static bool IsDomain(TNavigate::TEntry& entry) {
+ switch (entry.Kind) {
+ case NSchemeCache::TSchemeCacheNavigate::KindSubdomain:
+ case NSchemeCache::TSchemeCacheNavigate::KindExtSubdomain:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static bool IsDomain(TResolve::TEntry&) {
+ return false;
+ }
+
static TIntrusivePtr<TSecurityObject> GetSecurityObject(const TNavigate::TEntry& entry) {
return entry.SecurityObject;
}
@@ -235,61 +249,71 @@ namespace {
}
public:
- explicit TAclChecker(TContextPtr context)
+ explicit TAccessChecker(TContextPtr context)
: Context(context)
{
Y_VERIFY(!Context->WaitCounter);
}
void Bootstrap(const TActorContext&) {
- if (Context->Request->UserToken == nullptr) {
- SendResult();
- return;
- }
-
for (auto& entry : Context->Request->ResultSet) {
- auto securityObject = GetSecurityObject(entry);
- if (securityObject == nullptr) {
- continue;
+ if (!IsDomain(entry) && Context->ResolvedDomainInfo && entry.DomainInfo) {
+ // ^ It is allowed to describe subdomains by specifying root as DatabaseName
+
+ if (Context->ResolvedDomainInfo->DomainKey != entry.DomainInfo->DomainKey) {
+ SBC_LOG_W("Path does not belong to the specified domain"
+ << ": self# " << this->SelfId()
+ << ", domain# " << Context->ResolvedDomainInfo->DomainKey
+ << ", path's domain# " << entry.DomainInfo->DomainKey);
+
+ SetErrorAndClear(Context.Get(), entry);
+ }
}
+
+ if (Context->Request->UserToken) {
+ auto securityObject = GetSecurityObject(entry);
+ if (securityObject == nullptr) {
+ continue;
+ }
- const ui32 access = GetAccess(entry);
- if (!securityObject->CheckAccess(access, *Context->Request->UserToken)) {
- SBC_LOG_W("Access denied"
- << ": self# " << this->SelfId()
- << ", for# " << Context->Request->UserToken->GetUserSID()
- << ", access# " << NACLib::AccessRightsToString(access));
+ const ui32 access = GetAccess(entry);
+ if (!securityObject->CheckAccess(access, *Context->Request->UserToken)) {
+ SBC_LOG_W("Access denied"
+ << ": self# " << this->SelfId()
+ << ", for# " << Context->Request->UserToken->GetUserSID()
+ << ", access# " << NACLib::AccessRightsToString(access));
- SetErrorAndClear(Context.Get(), entry);
+ SetErrorAndClear(Context.Get(), entry);
+ }
}
}
SendResult();
}
- using TBase = TAclChecker<TContextPtr, TEvResult, TDerived>;
+ using TBase = TAccessChecker<TContextPtr, TEvResult, TDerived>;
private:
TContextPtr Context;
- }; // TAclChecker
+ }; // TAccessChecker
- class TAclCheckerNavigate: public TAclChecker<TNavigateContextPtr, TEvNavigateResult, TAclCheckerNavigate> {
+ class TAccessCheckerNavigate: public TAccessChecker<TNavigateContextPtr, TEvNavigateResult, TAccessCheckerNavigate> {
public:
using TBase::TBase;
};
- class TAclCheckerResolve: public TAclChecker<TResolveContextPtr, TEvResolveResult, TAclCheckerResolve> {
+ class TAccessCheckerResolve: public TAccessChecker<TResolveContextPtr, TEvResolveResult, TAccessCheckerResolve> {
public:
using TBase::TBase;
};
- IActor* CreateAclChecker(TNavigateContextPtr context) {
- return new TAclCheckerNavigate(context);
+ IActor* CreateAccessChecker(TNavigateContextPtr context) {
+ return new TAccessCheckerNavigate(context);
}
- IActor* CreateAclChecker(TResolveContextPtr context) {
- return new TAclCheckerResolve(context);
+ IActor* CreateAccessChecker(TResolveContextPtr context) {
+ return new TAccessCheckerResolve(context);
}
class TWatchCache: public TMonitorableActor<TWatchCache> {
@@ -2393,7 +2417,20 @@ class TSchemeCache: public TMonitorableActor<TSchemeCache> {
template <typename TContextPtr>
void Complete(TContextPtr context) {
Counters.FinishRequest(Now() - context->CreatedAt);
- Register(CreateAclChecker(context));
+ Register(CreateAccessChecker(context));
+ }
+
+ template <typename TContext, typename TEvent>
+ TIntrusivePtr<TContext> MakeContext(TEvent& ev) const {
+ TIntrusivePtr<TContext> context(new TContext(ev->Sender, ev->Get()->Request, Now()));
+
+ if (context->Request->DatabaseName) {
+ if (auto* db = Cache.FindPtr(CanonizePath(context->Request->DatabaseName))) {
+ context->ResolvedDomainInfo = db->GetDomainInfo();
+ }
+ }
+
+ return context;
}
void Handle(TEvTxProxySchemeCache::TEvNavigateKeySet::TPtr& ev) {
@@ -2405,7 +2442,7 @@ class TSchemeCache: public TMonitorableActor<TSchemeCache> {
return;
}
- TIntrusivePtr<TNavigateContext> context(new TNavigateContext(ev->Sender, ev->Get()->Request, Now()));
+ auto context = MakeContext<TNavigateContext>(ev);
for (size_t i = 0; i < context->Request->ResultSet.size(); ++i) {
auto& entry = context->Request->ResultSet[i];
@@ -2465,7 +2502,7 @@ class TSchemeCache: public TMonitorableActor<TSchemeCache> {
return;
}
- TIntrusivePtr<TResolveContext> context(new TResolveContext(ev->Sender, ev->Get()->Request, Now()));
+ auto context = MakeContext<TResolveContext>(ev);
auto pathExtractor = [](const TResolve::TEntry& entry) {
const TKeyDesc* keyDesc = entry.KeyDescription.Get();
diff --git a/ydb/core/tx/scheme_board/cache_ut.cpp b/ydb/core/tx/scheme_board/cache_ut.cpp
index c27b3517b34..8630e459817 100644
--- a/ydb/core/tx/scheme_board/cache_ut.cpp
+++ b/ydb/core/tx/scheme_board/cache_ut.cpp
@@ -57,6 +57,7 @@ public:
UNIT_TEST(MigrationUndo);
UNIT_TEST(MigrationDeletedPathNavigate);
UNIT_TEST(WatchRoot);
+ UNIT_TEST(PathBelongsToDomain);
UNIT_TEST_SUITE_END();
void Navigate();
@@ -76,6 +77,7 @@ public:
void MigrationUndo();
void MigrationDeletedPathNavigate();
void WatchRoot();
+ void PathBelongsToDomain();
protected:
TNavigate::TEntry TestNavigateImpl(THolder<TNavigate> request, TNavigate::EStatus expectedStatus,
@@ -948,6 +950,48 @@ void TCacheTest::WatchRoot() {
SimulateSleep(*Context, TDuration::Seconds(1));
}
+void TCacheTest::PathBelongsToDomain() {
+ ui64 txId = 100;
+ TestCreateSubDomain(*Context, ++txId, "/Root", "Name: \"SubDomain\"");
+ TestWaitNotification(*Context, {txId}, CreateNotificationSubscriber(*Context, TTestTxConfig::SchemeShard));
+ TestMkDir(*Context, ++txId, "/Root/SubDomain", "DirA");
+
+ TTableId testId;
+
+ // ok
+ {
+ auto request = MakeHolder<TNavigate>();
+ request->DatabaseName = "/Root/SubDomain";
+ auto& entry = request->ResultSet.emplace_back();
+ entry.Path = SplitPath("/Root/SubDomain/DirA");
+ entry.RequestType = TNavigate::TEntry::ERequestType::ByPath;
+ auto result = TestNavigateImpl(std::move(request), TNavigate::EStatus::Ok,
+ "", TNavigate::EOp::OpPath, false, true);
+
+ testId = result.TableId;
+ }
+ // error, by path
+ {
+ auto request = MakeHolder<TNavigate>();
+ request->DatabaseName = "/Root";
+ auto& entry = request->ResultSet.emplace_back();
+ entry.Path = SplitPath("/Root/SubDomain/DirA");
+ entry.RequestType = TNavigate::TEntry::ERequestType::ByPath;
+ auto result = TestNavigateImpl(std::move(request), TNavigate::EStatus::PathErrorUnknown,
+ "", TNavigate::EOp::OpPath, false, true);
+ }
+ // error, by path id
+ {
+ auto request = MakeHolder<TNavigate>();
+ request->DatabaseName = "/Root";
+ auto& entry = request->ResultSet.emplace_back();
+ entry.TableId = testId;
+ entry.RequestType = TNavigate::TEntry::ERequestType::ByTableId;
+ auto result = TestNavigateImpl(std::move(request), TNavigate::EStatus::PathErrorUnknown,
+ "", TNavigate::EOp::OpPath, false, true);
+ }
+}
+
class TCacheTestWithDrops: public TCacheTest {
public:
TTestContext::TEventObserver ObserverFunc() override {
diff --git a/ydb/core/tx/scheme_cache/scheme_cache.h b/ydb/core/tx/scheme_cache/scheme_cache.h
index 06365155035..3e86fba52af 100644
--- a/ydb/core/tx/scheme_cache/scheme_cache.h
+++ b/ydb/core/tx/scheme_cache/scheme_cache.h
@@ -345,6 +345,7 @@ struct TSchemeCacheRequestContext : TAtomicRefCount<TSchemeCacheRequestContext>,
ui64 WaitCounter;
TAutoPtr<TSchemeCacheRequest> Request;
const TInstant CreatedAt;
+ TIntrusivePtr<TDomainInfo> ResolvedDomainInfo; // resolved from DatabaseName
TSchemeCacheRequestContext(const TActorId& sender, TAutoPtr<TSchemeCacheRequest> request, const TInstant& now = TInstant::Now())
: Sender(sender)
@@ -359,6 +360,7 @@ struct TSchemeCacheNavigateContext : TAtomicRefCount<TSchemeCacheNavigateContext
ui64 WaitCounter;
TAutoPtr<TSchemeCacheNavigate> Request;
const TInstant CreatedAt;
+ TIntrusivePtr<TDomainInfo> ResolvedDomainInfo; // resolved from DatabaseName
TSchemeCacheNavigateContext(const TActorId& sender, TAutoPtr<TSchemeCacheNavigate> request, const TInstant& now = TInstant::Now())
: Sender(sender)
diff --git a/ydb/tests/functional/tenants/test_dynamic_tenants.py b/ydb/tests/functional/tenants/test_dynamic_tenants.py
index bdf7d597824..1ea37838e85 100644
--- a/ydb/tests/functional/tenants/test_dynamic_tenants.py
+++ b/ydb/tests/functional/tenants/test_dynamic_tenants.py
@@ -404,6 +404,6 @@ class TestCheckAccess(DBWithDynamicSlot):
calling(client.list_directory).with_args(
'/Root/'
),
- raises(ydb.Unauthorized)
+ raises(ydb.SchemeError)
)
client.list_directory('/')
diff --git a/ydb/tests/functional/tenants/test_tenants.py b/ydb/tests/functional/tenants/test_tenants.py
index 138297d8ccd..f295e8740d6 100644
--- a/ydb/tests/functional/tenants/test_tenants.py
+++ b/ydb/tests/functional/tenants/test_tenants.py
@@ -373,12 +373,6 @@ class TestTenants(DBForStaticSlots):
assert len(result.children) > 0
assert result.children[0].name == ".sys"
- result = driver.scheme_client.list_directory(above_database)
- logger.debug("From database: list above database <%s> is %s", above_database, convert(result))
- assert len(result.children) > 0
- assert result.children[0].name == basename
- assert result.children[0].type == ydb.scheme.SchemeEntryType.DATABASE
-
driver_config_for_root = ydb.DriverConfig(
"%s:%s" % (self.cluster.nodes[1].host, self.cluster.nodes[1].port),
self.root_dir