Skip to content

Commit

Permalink
Use the root domain as a database for all operations with users and g…
Browse files Browse the repository at this point in the history
…roups (#13969)
  • Loading branch information
andrewstalin authored Feb 3, 2025
1 parent df18e01 commit 9ffc501
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
20 changes: 20 additions & 0 deletions ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -120,6 +123,15 @@ class TKqpSchemeExecuter : public TActorBootstrapped<TKqpSchemeExecuter> {
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;

Expand Down Expand Up @@ -181,18 +193,21 @@ class TKqpSchemeExecuter : public TActorBootstrapped<TKqpSchemeExecuter> {
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: {
Expand All @@ -214,30 +229,35 @@ class TKqpSchemeExecuter : public TActorBootstrapped<TKqpSchemeExecuter> {
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;
}

Expand Down
132 changes: 132 additions & 0 deletions ydb/tests/functional/tenants/test_users_groups_with_acl.py
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions ydb/tests/functional/tenants/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 9ffc501

Please sign in to comment.