Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RBAC-5.2 #9182

Merged
merged 12 commits into from
Feb 22, 2020
2 changes: 1 addition & 1 deletion dbms/programs/server/MySQLHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void MySQLHandler::authenticate(const String & user_name, const String & auth_pl
try
{
// For compatibility with JavaScript MySQL client, Native41 authentication plugin is used when possible (if password is specified using double SHA1). Otherwise SHA256 plugin is used.
auto user = connection_context.getAccessControlManager().getUser(user_name);
auto user = connection_context.getAccessControlManager().read<User>(user_name);
const DB::Authentication::Type user_auth_type = user->authentication.getType();
if (user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD)
{
Expand Down
2 changes: 1 addition & 1 deletion dbms/programs/server/TCPHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ void TCPHandler::receiveQuery()
}
else
{
query_context->switchRowPolicy();
query_context->setInitialRowPolicy();
}
}

Expand Down
83 changes: 26 additions & 57 deletions dbms/src/Access/AccessControlManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
#include <Access/MultipleAccessStorage.h>
#include <Access/MemoryAccessStorage.h>
#include <Access/UsersConfigAccessStorage.h>
#include <Access/User.h>
#include <Access/QuotaContextFactory.h>
#include <Access/AccessRightsContextFactory.h>
#include <Access/RoleContextFactory.h>
#include <Access/RowPolicyContextFactory.h>
#include <Access/AccessRightsContext.h>
#include <Access/QuotaContextFactory.h>


namespace DB
Expand All @@ -24,8 +24,10 @@ namespace

AccessControlManager::AccessControlManager()
: MultipleAccessStorage(createStorages()),
quota_context_factory(std::make_unique<QuotaContextFactory>(*this)),
row_policy_context_factory(std::make_unique<RowPolicyContextFactory>(*this))
access_rights_context_factory(std::make_unique<AccessRightsContextFactory>(*this)),
role_context_factory(std::make_unique<RoleContextFactory>(*this)),
row_policy_context_factory(std::make_unique<RowPolicyContextFactory>(*this)),
quota_context_factory(std::make_unique<QuotaContextFactory>(*this))
{
}

Expand All @@ -35,70 +37,43 @@ AccessControlManager::~AccessControlManager()
}


UserPtr AccessControlManager::getUser(
const String & user_name, std::function<void(const UserPtr &)> on_change, ext::scope_guard * subscription) const
{
return getUser(getID<User>(user_name), std::move(on_change), subscription);
}


UserPtr AccessControlManager::getUser(
const UUID & user_id, std::function<void(const UserPtr &)> on_change, ext::scope_guard * subscription) const
{
if (on_change && subscription)
{
*subscription = subscribeForChanges(user_id, [on_change](const UUID &, const AccessEntityPtr & user)
{
if (user)
on_change(typeid_cast<UserPtr>(user));
});
}
return read<User>(user_id);
}


UserPtr AccessControlManager::authorizeAndGetUser(
const String & user_name,
const String & password,
const Poco::Net::IPAddress & address,
std::function<void(const UserPtr &)> on_change,
ext::scope_guard * subscription) const
void AccessControlManager::loadFromConfig(const Poco::Util::AbstractConfiguration & users_config)
{
return authorizeAndGetUser(getID<User>(user_name), password, address, std::move(on_change), subscription);
auto & users_config_access_storage = dynamic_cast<UsersConfigAccessStorage &>(getStorageByIndex(1));
users_config_access_storage.loadFromConfig(users_config);
}


UserPtr AccessControlManager::authorizeAndGetUser(
AccessRightsContextPtr AccessControlManager::getAccessRightsContext(
const UUID & user_id,
const String & password,
const Poco::Net::IPAddress & address,
std::function<void(const UserPtr &)> on_change,
ext::scope_guard * subscription) const
const std::vector<UUID> & current_roles,
bool use_default_roles,
const Settings & settings,
const String & current_database,
const ClientInfo & client_info) const
{
auto user = getUser(user_id, on_change, subscription);
user->allowed_client_hosts.checkContains(address, user->getName());
user->authentication.checkPassword(password, user->getName());
return user;
return access_rights_context_factory->createContext(user_id, current_roles, use_default_roles, settings, current_database, client_info);
}


void AccessControlManager::loadFromConfig(const Poco::Util::AbstractConfiguration & users_config)
RoleContextPtr AccessControlManager::getRoleContext(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const
{
auto & users_config_access_storage = dynamic_cast<UsersConfigAccessStorage &>(getStorageByIndex(1));
users_config_access_storage.loadFromConfig(users_config);
return role_context_factory->createContext(current_roles, current_roles_with_admin_option);
}


std::shared_ptr<const AccessRightsContext> AccessControlManager::getAccessRightsContext(const UserPtr & user, const ClientInfo & client_info, const Settings & settings, const String & current_database)
RowPolicyContextPtr AccessControlManager::getRowPolicyContext(const UUID & user_id, const std::vector<UUID> & enabled_roles) const
{
return std::make_shared<AccessRightsContext>(user, client_info, settings, current_database);
return row_policy_context_factory->createContext(user_id, enabled_roles);
}


std::shared_ptr<QuotaContext> AccessControlManager::createQuotaContext(
const String & user_name, const Poco::Net::IPAddress & address, const String & custom_quota_key)
QuotaContextPtr AccessControlManager::getQuotaContext(
const String & user_name, const UUID & user_id, const std::vector<UUID> & enabled_roles, const Poco::Net::IPAddress & address, const String & custom_quota_key) const
{
return quota_context_factory->createContext(user_name, address, custom_quota_key);
return quota_context_factory->createContext(user_name, user_id, enabled_roles, address, custom_quota_key);
}


Expand All @@ -107,10 +82,4 @@ std::vector<QuotaUsageInfo> AccessControlManager::getQuotaUsageInfo() const
return quota_context_factory->getUsageInfo();
}


std::shared_ptr<RowPolicyContext> AccessControlManager::getRowPolicyContext(const String & user_name) const
{
return row_policy_context_factory->createContext(user_name);
}

}
48 changes: 33 additions & 15 deletions dbms/src/Access/AccessControlManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <Access/MultipleAccessStorage.h>
#include <Poco/AutoPtr.h>
#include <ext/scope_guard.h>
#include <memory>


Expand All @@ -20,15 +19,21 @@ namespace Poco

namespace DB
{
class AccessRightsContext;
using AccessRightsContextPtr = std::shared_ptr<const AccessRightsContext>;
class AccessRightsContextFactory;
struct User;
using UserPtr = std::shared_ptr<const User>;
struct RoleContext;
using RoleContextPtr = std::shared_ptr<const RoleContext>;
class RoleContextFactory;
class RowPolicyContext;
using RowPolicyContextPtr = std::shared_ptr<const RowPolicyContext>;
class RowPolicyContextFactory;
class QuotaContext;
using QuotaContextPtr = std::shared_ptr<const QuotaContext>;
class QuotaContextFactory;
struct QuotaUsageInfo;
class RowPolicyContext;
class RowPolicyContextFactory;
class AccessRights;
class AccessRightsContext;
class ClientInfo;
struct Settings;

Expand All @@ -42,23 +47,36 @@ class AccessControlManager : public MultipleAccessStorage

void loadFromConfig(const Poco::Util::AbstractConfiguration & users_config);

UserPtr getUser(const String & user_name, std::function<void(const UserPtr &)> on_change = {}, ext::scope_guard * subscription = nullptr) const;
UserPtr getUser(const UUID & user_id, std::function<void(const UserPtr &)> on_change = {}, ext::scope_guard * subscription = nullptr) const;
UserPtr authorizeAndGetUser(const String & user_name, const String & password, const Poco::Net::IPAddress & address, std::function<void(const UserPtr &)> on_change = {}, ext::scope_guard * subscription = nullptr) const;
UserPtr authorizeAndGetUser(const UUID & user_id, const String & password, const Poco::Net::IPAddress & address, std::function<void(const UserPtr &)> on_change = {}, ext::scope_guard * subscription = nullptr) const;
AccessRightsContextPtr getAccessRightsContext(
const UUID & user_id,
const std::vector<UUID> & current_roles,
bool use_default_roles,
const Settings & settings,
const String & current_database,
const ClientInfo & client_info) const;

std::shared_ptr<const AccessRightsContext> getAccessRightsContext(const UserPtr & user, const ClientInfo & client_info, const Settings & settings, const String & current_database);
RoleContextPtr getRoleContext(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const;

std::shared_ptr<QuotaContext>
createQuotaContext(const String & user_name, const Poco::Net::IPAddress & address, const String & custom_quota_key);
RowPolicyContextPtr getRowPolicyContext(
const UUID & user_id,
const std::vector<UUID> & enabled_roles) const;

std::vector<QuotaUsageInfo> getQuotaUsageInfo() const;
QuotaContextPtr getQuotaContext(
const String & user_name,
const UUID & user_id,
const std::vector<UUID> & enabled_roles,
const Poco::Net::IPAddress & address,
const String & custom_quota_key) const;

std::shared_ptr<RowPolicyContext> getRowPolicyContext(const String & user_name) const;
std::vector<QuotaUsageInfo> getQuotaUsageInfo() const;

private:
std::unique_ptr<QuotaContextFactory> quota_context_factory;
std::unique_ptr<AccessRightsContextFactory> access_rights_context_factory;
std::unique_ptr<RoleContextFactory> role_context_factory;
std::unique_ptr<RowPolicyContextFactory> row_policy_context_factory;
std::unique_ptr<QuotaContextFactory> quota_context_factory;
};

}
26 changes: 12 additions & 14 deletions dbms/src/Access/AccessFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,10 @@ class AccessFlags::Impl
ext::push_back(all, std::move(alter));

auto create_database = std::make_unique<Node>("CREATE DATABASE", next_flag++, DATABASE_LEVEL);
ext::push_back(create_database->aliases, "ATTACH DATABASE");
auto create_table = std::make_unique<Node>("CREATE TABLE", next_flag++, TABLE_LEVEL);
ext::push_back(create_table->aliases, "ATTACH TABLE");
auto create_view = std::make_unique<Node>("CREATE VIEW", next_flag++, VIEW_LEVEL);
ext::push_back(create_view->aliases, "ATTACH VIEW");
auto create_dictionary = std::make_unique<Node>("CREATE DICTIONARY", next_flag++, DICTIONARY_LEVEL);
ext::push_back(create_dictionary->aliases, "ATTACH DICTIONARY");
auto create = std::make_unique<Node>("CREATE", std::move(create_database), std::move(create_table), std::move(create_view), std::move(create_dictionary));
ext::push_back(create->aliases, "ATTACH");
ext::push_back(all, std::move(create));

auto create_temporary_table = std::make_unique<Node>("CREATE TEMPORARY TABLE", next_flag++, GLOBAL_LEVEL);
Expand All @@ -325,13 +320,6 @@ class AccessFlags::Impl
auto drop = std::make_unique<Node>("DROP", std::move(drop_database), std::move(drop_table), std::move(drop_view), std::move(drop_dictionary));
ext::push_back(all, std::move(drop));

auto detach_database = std::make_unique<Node>("DETACH DATABASE", next_flag++, DATABASE_LEVEL);
auto detach_table = std::make_unique<Node>("DETACH TABLE", next_flag++, TABLE_LEVEL);
auto detach_view = std::make_unique<Node>("DETACH VIEW", next_flag++, VIEW_LEVEL);
auto detach_dictionary = std::make_unique<Node>("DETACH DICTIONARY", next_flag++, DICTIONARY_LEVEL);
auto detach = std::make_unique<Node>("DETACH", std::move(detach_database), std::move(detach_table), std::move(detach_view), std::move(detach_dictionary));
ext::push_back(all, std::move(detach));

auto truncate_table = std::make_unique<Node>("TRUNCATE TABLE", next_flag++, TABLE_LEVEL);
auto truncate_view = std::make_unique<Node>("TRUNCATE VIEW", next_flag++, VIEW_LEVEL);
auto truncate = std::make_unique<Node>("TRUNCATE", std::move(truncate_table), std::move(truncate_view));
Expand All @@ -347,8 +335,18 @@ class AccessFlags::Impl
ext::push_back(all, std::move(kill));

auto create_user = std::make_unique<Node>("CREATE USER", next_flag++, GLOBAL_LEVEL);
ext::push_back(create_user->aliases, "ALTER USER", "DROP USER", "CREATE ROLE", "DROP ROLE", "CREATE POLICY", "ALTER POLICY", "DROP POLICY", "CREATE QUOTA", "ALTER QUOTA", "DROP QUOTA");
ext::push_back(all, std::move(create_user));
auto alter_user = std::make_unique<Node>("ALTER USER", next_flag++, GLOBAL_LEVEL);
auto drop_user = std::make_unique<Node>("DROP USER", next_flag++, GLOBAL_LEVEL);
auto create_role = std::make_unique<Node>("CREATE ROLE", next_flag++, GLOBAL_LEVEL);
auto drop_role = std::make_unique<Node>("DROP ROLE", next_flag++, GLOBAL_LEVEL);
auto create_policy = std::make_unique<Node>("CREATE POLICY", next_flag++, GLOBAL_LEVEL);
auto alter_policy = std::make_unique<Node>("ALTER POLICY", next_flag++, GLOBAL_LEVEL);
auto drop_policy = std::make_unique<Node>("DROP POLICY", next_flag++, GLOBAL_LEVEL);
auto create_quota = std::make_unique<Node>("CREATE QUOTA", next_flag++, GLOBAL_LEVEL);
auto alter_quota = std::make_unique<Node>("ALTER QUOTA", next_flag++, GLOBAL_LEVEL);
auto drop_quota = std::make_unique<Node>("DROP QUOTA", next_flag++, GLOBAL_LEVEL);
auto role_admin = std::make_unique<Node>("ROLE ADMIN", next_flag++, GLOBAL_LEVEL);
ext::push_back(all, std::move(create_user), std::move(alter_user), std::move(drop_user), std::move(create_role), std::move(drop_role), std::move(create_policy), std::move(alter_policy), std::move(drop_policy), std::move(create_quota), std::move(alter_quota), std::move(drop_quota), std::move(role_admin));

auto shutdown = std::make_unique<Node>("SHUTDOWN", next_flag++, GLOBAL_LEVEL);
ext::push_back(shutdown->aliases, "SYSTEM SHUTDOWN", "SYSTEM KILL");
Expand Down