aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandrew stalin <andrew.stalin@gmail.com>2025-02-03 11:23:32 +0700
committerGitHub <noreply@github.com>2025-02-03 11:23:32 +0700
commit9ffc50105c01aef1f027fdff825e5a14b9a3553f (patch)
tree8c668935f8c18c53f702935d3b7b1bdb22be7ca0
parentdf18e0111b39e51b00c161320ea91c7ce929a648 (diff)
downloadydb-9ffc50105c01aef1f027fdff825e5a14b9a3553f.tar.gz
Use the root domain as a database for all operations with users and groups (#13969)
-rw-r--r--ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp20
-rw-r--r--ydb/tests/functional/tenants/test_users_groups_with_acl.py132
-rw-r--r--ydb/tests/functional/tenants/ya.make1
3 files changed, 153 insertions, 0 deletions
diff --git a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
index f118fe0da40..3794f9a30df 100644
--- a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
+++ b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
@@ -4,12 +4,15 @@
#include <ydb/core/kqp/gateway/actors/analyze_actor.h>
#include <ydb/core/kqp/gateway/actors/scheme.h>
#include <ydb/core/kqp/gateway/local_rpc/helper.h>
+#include <ydb/core/kqp/gateway/utils/scheme_helpers.h>
#include <ydb/core/kqp/session_actor/kqp_worker_common.h>
+#include <ydb/core/protos/auth.pb.h>
#include <ydb/core/protos/schemeshard/operations.pb.h>
#include <ydb/core/tx/schemeshard/schemeshard_build_index.h>
#include <ydb/core/tx/tx_proxy/proxy.h>
#include <ydb/services/metadata/abstract/kqp_common.h>
+
namespace NKikimr::NKqp {
using namespace NThreading;
@@ -120,6 +123,15 @@ public:
Become(&TKqpSchemeExecuter::ExecuteState);
}
+ TString GetDatabaseForLoginOperation() const {
+ const auto domainLoginOnly = AppData()->AuthConfig.GetDomainLoginOnly();
+ const auto domain = AppData()->DomainsInfo ? AppData()->DomainsInfo->GetDomain() : nullptr;
+ const auto domainName = domain ? domain->Name : "";
+ TString database;
+ return NSchemeHelpers::SetDatabaseForLoginOperation(database, domainLoginOnly, domainName, Database)
+ ? database : Database;
+ }
+
void MakeSchemeOperationRequest() {
using TRequest = TEvTxUserProxy::TEvProposeTransaction;
@@ -181,18 +193,21 @@ public:
case NKqpProto::TKqpSchemeOperation::kCreateUser: {
const auto& modifyScheme = schemeOp.GetCreateUser();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kAlterUser: {
const auto& modifyScheme = schemeOp.GetAlterUser();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kDropUser: {
const auto& modifyScheme = schemeOp.GetDropUser();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kCreateExternalTable: {
@@ -214,30 +229,35 @@ public:
case NKqpProto::TKqpSchemeOperation::kCreateGroup: {
const auto& modifyScheme = schemeOp.GetCreateGroup();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kAddGroupMembership: {
const auto& modifyScheme = schemeOp.GetAddGroupMembership();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kRemoveGroupMembership: {
const auto& modifyScheme = schemeOp.GetRemoveGroupMembership();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kRenameGroup: {
const auto& modifyScheme = schemeOp.GetRenameGroup();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
case NKqpProto::TKqpSchemeOperation::kDropGroup: {
const auto& modifyScheme = schemeOp.GetDropGroup();
ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ ev->Record.SetDatabaseName(GetDatabaseForLoginOperation());
break;
}
diff --git a/ydb/tests/functional/tenants/test_users_groups_with_acl.py b/ydb/tests/functional/tenants/test_users_groups_with_acl.py
new file mode 100644
index 00000000000..80be6eb38fa
--- /dev/null
+++ b/ydb/tests/functional/tenants/test_users_groups_with_acl.py
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+
+import logging
+import pytest
+from ydb.tests.library.harness.kikimr_config import KikimrConfigGenerator
+from ydb.tests.library.harness.ydb_fixtures import ydb_database_ctx
+from ydb.tests.oss.ydb_sdk_import import ydb
+
+
+logger = logging.getLogger(__name__)
+
+
+DATABASE = '/Root/users/database'
+
+
+@pytest.fixture(scope='module', params=[True, False], ids=['domain_login_only--true', 'domain_login_only--false'])
+def domain_login_only(request):
+ return request.param
+
+
+@pytest.fixture(scope='module')
+def ydb_configurator(ydb_cluster_configuration, domain_login_only):
+ config_generator = KikimrConfigGenerator(**ydb_cluster_configuration)
+ config_generator.yaml_config['auth_config'] = {
+ 'domain_login_only': domain_login_only,
+ }
+ return config_generator
+
+
+@pytest.fixture(scope='function')
+def domain_admin_driver_config(ydb_endpoint):
+ return ydb.DriverConfig(
+ endpoint=ydb_endpoint,
+ database="/Root",
+ )
+
+
+@pytest.fixture(scope='function')
+def tenant_admin_driver_config(ydb_endpoint):
+ return ydb.DriverConfig(
+ endpoint=ydb_endpoint,
+ database=DATABASE,
+ )
+
+
+@pytest.fixture(scope='function')
+def tenant_user_driver_config(ydb_endpoint):
+ return ydb.DriverConfig(
+ endpoint=ydb_endpoint,
+ database=DATABASE,
+ credentials=ydb.StaticCredentials.from_user_password('user', ''),
+ )
+
+
+def yql_create_user(config):
+ with ydb.Driver(config) as driver:
+ driver.wait()
+ script_client = ydb.ScriptingClient(driver)
+ script_client.execute_yql('CREATE USER user;')
+ script_client.execute_yql('ALTER USER user WITH PASSWORD NULL;')
+ script_client.execute_yql('DROP USER user;')
+
+
+def query_create_user(config):
+ with ydb.Driver(config) as driver:
+ with ydb.QuerySessionPool(driver, size=1) as pool:
+ pool.execute_with_retries('CREATE USER user;')
+ pool.execute_with_retries('ALTER USER user WITH PASSWORD NULL;')
+ pool.execute_with_retries('DROP USER user;')
+
+
+def yql_create_group(config):
+ with ydb.Driver(config) as driver:
+ driver.wait()
+ script_client = ydb.ScriptingClient(driver)
+ script_client.execute_yql('CREATE GROUP group;')
+ script_client.execute_yql('CREATE USER user;')
+ script_client.execute_yql('ALTER GROUP group ADD USER user;')
+ script_client.execute_yql('ALTER GROUP group DROP USER user;')
+ script_client.execute_yql('DROP GROUP group;')
+ script_client.execute_yql('DROP USER user;')
+
+
+def query_create_group(config):
+ with ydb.Driver(config) as driver:
+ with ydb.QuerySessionPool(driver, size=1) as pool:
+ pool.execute_with_retries('CREATE GROUP group;')
+ pool.execute_with_retries('CREATE USER user;')
+ pool.execute_with_retries('ALTER GROUP group ADD USER user;')
+ pool.execute_with_retries('ALTER GROUP group DROP USER user;')
+ pool.execute_with_retries('DROP GROUP group;')
+ pool.execute_with_retries('DROP USER user;')
+
+
+def test_yql_create_user_by_domain_admin(ydb_cluster, domain_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ yql_create_user(domain_admin_driver_config)
+
+
+def test_yql_create_user_by_tenant_admin(ydb_cluster, tenant_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ yql_create_user(tenant_admin_driver_config)
+
+
+def test_yql_create_group_by_domain_admin(ydb_cluster, domain_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ yql_create_group(domain_admin_driver_config)
+
+
+def test_yql_create_group_by_tenant_admin(ydb_cluster, tenant_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ yql_create_group(tenant_admin_driver_config)
+
+
+def test_query_create_user_by_domain_admin(ydb_cluster, domain_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ query_create_user(domain_admin_driver_config)
+
+
+def test_query_create_user_by_tenant_admin(ydb_cluster, tenant_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ query_create_user(tenant_admin_driver_config)
+
+
+def test_query_create_group_by_domain_admin(ydb_cluster, domain_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ query_create_group(domain_admin_driver_config)
+
+
+def test_query_create_group_by_tenant_admin(ydb_cluster, tenant_admin_driver_config):
+ with ydb_database_ctx(ydb_cluster, DATABASE):
+ query_create_group(tenant_admin_driver_config)
diff --git a/ydb/tests/functional/tenants/ya.make b/ydb/tests/functional/tenants/ya.make
index f9e02d4d2f5..3f0c2acabf5 100644
--- a/ydb/tests/functional/tenants/ya.make
+++ b/ydb/tests/functional/tenants/ya.make
@@ -10,6 +10,7 @@ TEST_SRCS(
test_storage_config.py
test_system_views.py
test_publish_into_schemeboard_with_common_ssring.py
+ test_users_groups_with_acl.py
)
SPLIT_FACTOR(20)