2020-03-07 17:37:38 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Access/AccessRights.h>
|
2021-11-18 13:04:42 +00:00
|
|
|
#include <Access/Common/RowPolicyDefs.h>
|
2020-03-07 17:37:38 +00:00
|
|
|
#include <Interpreters/ClientInfo.h>
|
|
|
|
#include <Core/UUID.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/scope_guard.h>
|
|
|
|
#include <base/shared_ptr_helper.h>
|
2020-03-07 17:37:38 +00:00
|
|
|
#include <boost/container/flat_set.hpp>
|
|
|
|
#include <mutex>
|
2021-11-18 20:54:18 +00:00
|
|
|
#include <optional>
|
2021-11-02 13:05:33 +00:00
|
|
|
#include <unordered_map>
|
2020-03-07 17:37:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace Poco { class Logger; }
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
struct User;
|
|
|
|
using UserPtr = std::shared_ptr<const User>;
|
|
|
|
struct EnabledRolesInfo;
|
|
|
|
class EnabledRoles;
|
|
|
|
class EnabledRowPolicies;
|
|
|
|
class EnabledQuota;
|
2020-03-04 22:27:03 +00:00
|
|
|
class EnabledSettings;
|
2020-05-08 12:50:45 +00:00
|
|
|
struct QuotaUsage;
|
2020-03-07 17:37:38 +00:00
|
|
|
struct Settings;
|
2021-07-22 16:07:03 +00:00
|
|
|
struct SettingsProfilesInfo;
|
|
|
|
class SettingsChanges;
|
2021-11-02 11:06:20 +00:00
|
|
|
class AccessControl;
|
2020-03-07 17:37:38 +00:00
|
|
|
class IAST;
|
|
|
|
using ASTPtr = std::shared_ptr<IAST>;
|
|
|
|
|
|
|
|
|
2020-06-20 22:44:52 +00:00
|
|
|
struct ContextAccessParams
|
|
|
|
{
|
|
|
|
std::optional<UUID> user_id;
|
|
|
|
boost::container::flat_set<UUID> current_roles;
|
|
|
|
bool use_default_roles = false;
|
|
|
|
UInt64 readonly = 0;
|
|
|
|
bool allow_ddl = false;
|
|
|
|
bool allow_introspection = false;
|
|
|
|
String current_database;
|
|
|
|
ClientInfo::Interface interface = ClientInfo::Interface::TCP;
|
|
|
|
ClientInfo::HTTPMethod http_method = ClientInfo::HTTPMethod::UNKNOWN;
|
|
|
|
Poco::Net::IPAddress address;
|
2020-12-01 21:07:20 +00:00
|
|
|
String forwarded_address;
|
2020-06-20 22:44:52 +00:00
|
|
|
String quota_key;
|
|
|
|
|
2020-12-01 21:07:20 +00:00
|
|
|
auto toTuple() const
|
|
|
|
{
|
|
|
|
return std::tie(
|
|
|
|
user_id, current_roles, use_default_roles, readonly, allow_ddl, allow_introspection,
|
|
|
|
current_database, interface, http_method, address, forwarded_address, quota_key);
|
|
|
|
}
|
|
|
|
|
2020-06-20 22:44:52 +00:00
|
|
|
friend bool operator ==(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return lhs.toTuple() == rhs.toTuple(); }
|
|
|
|
friend bool operator !=(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return !(lhs == rhs); }
|
|
|
|
friend bool operator <(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return lhs.toTuple() < rhs.toTuple(); }
|
|
|
|
friend bool operator >(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return rhs < lhs; }
|
|
|
|
friend bool operator <=(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return !(rhs < lhs); }
|
|
|
|
friend bool operator >=(const ContextAccessParams & lhs, const ContextAccessParams & rhs) { return !(lhs < rhs); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-03-07 17:37:38 +00:00
|
|
|
class ContextAccess
|
|
|
|
{
|
|
|
|
public:
|
2020-06-20 22:44:52 +00:00
|
|
|
using Params = ContextAccessParams;
|
2020-03-07 17:37:38 +00:00
|
|
|
const Params & getParams() const { return params; }
|
2020-04-29 19:35:56 +00:00
|
|
|
|
|
|
|
/// Returns the current user. The function can return nullptr.
|
2020-03-07 17:37:38 +00:00
|
|
|
UserPtr getUser() const;
|
|
|
|
String getUserName() const;
|
2021-08-01 14:12:34 +00:00
|
|
|
std::optional<UUID> getUserID() const { return getParams().user_id; }
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-04-29 19:35:56 +00:00
|
|
|
/// Returns information about current and enabled roles.
|
2020-03-07 17:37:38 +00:00
|
|
|
std::shared_ptr<const EnabledRolesInfo> getRolesInfo() const;
|
|
|
|
|
2020-04-29 19:35:56 +00:00
|
|
|
/// Returns information about enabled row policies.
|
2020-05-07 02:45:27 +00:00
|
|
|
std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies() const;
|
2020-04-29 19:35:56 +00:00
|
|
|
|
|
|
|
/// Returns the row policy filter for a specified table.
|
|
|
|
/// The function returns nullptr if there is no filter to apply.
|
2021-11-18 13:04:42 +00:00
|
|
|
ASTPtr getRowPolicyFilter(const String & database, const String & table_name, RowPolicyFilterType filter_type, const ASTPtr & combine_with_expr = nullptr) const;
|
2020-04-29 19:35:56 +00:00
|
|
|
|
|
|
|
/// Returns the quota to track resource consumption.
|
2020-03-07 17:37:38 +00:00
|
|
|
std::shared_ptr<const EnabledQuota> getQuota() const;
|
2020-05-08 12:50:45 +00:00
|
|
|
std::optional<QuotaUsage> getQuotaUsage() const;
|
2020-04-29 19:35:56 +00:00
|
|
|
|
2021-07-22 16:07:03 +00:00
|
|
|
/// Returns the default settings, i.e. the settings which should be applied on user's login.
|
|
|
|
SettingsChanges getDefaultSettings() const;
|
|
|
|
std::shared_ptr<const SettingsProfilesInfo> getDefaultProfileInfo() const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-06-20 22:44:52 +00:00
|
|
|
/// Returns the current access rights.
|
2020-12-08 14:24:32 +00:00
|
|
|
std::shared_ptr<const AccessRights> getAccessRights() const;
|
|
|
|
std::shared_ptr<const AccessRights> getAccessRightsWithImplicit() const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-06-20 22:44:52 +00:00
|
|
|
/// Checks if a specified access is granted, and throws an exception if not.
|
|
|
|
/// Empty database means the current database.
|
|
|
|
void checkAccess(const AccessFlags & flags) const;
|
|
|
|
void checkAccess(const AccessFlags & flags, const std::string_view & database) const;
|
|
|
|
void checkAccess(const AccessFlags & flags, const std::string_view & database, const std::string_view & table) const;
|
|
|
|
void checkAccess(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::string_view & column) const;
|
|
|
|
void checkAccess(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::vector<std::string_view> & columns) const;
|
|
|
|
void checkAccess(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const Strings & columns) const;
|
|
|
|
void checkAccess(const AccessRightsElement & element) const;
|
|
|
|
void checkAccess(const AccessRightsElements & elements) const;
|
|
|
|
|
2020-03-07 17:37:38 +00:00
|
|
|
void checkGrantOption(const AccessFlags & flags) const;
|
|
|
|
void checkGrantOption(const AccessFlags & flags, const std::string_view & database) const;
|
|
|
|
void checkGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table) const;
|
|
|
|
void checkGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::string_view & column) const;
|
|
|
|
void checkGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::vector<std::string_view> & columns) const;
|
|
|
|
void checkGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const Strings & columns) const;
|
|
|
|
void checkGrantOption(const AccessRightsElement & element) const;
|
|
|
|
void checkGrantOption(const AccessRightsElements & elements) const;
|
|
|
|
|
2021-02-26 22:37:00 +00:00
|
|
|
/// Checks if a specified access is granted, and returns false if not.
|
|
|
|
/// Empty database means the current database.
|
|
|
|
bool isGranted(const AccessFlags & flags) const;
|
|
|
|
bool isGranted(const AccessFlags & flags, const std::string_view & database) const;
|
|
|
|
bool isGranted(const AccessFlags & flags, const std::string_view & database, const std::string_view & table) const;
|
|
|
|
bool isGranted(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::string_view & column) const;
|
|
|
|
bool isGranted(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::vector<std::string_view> & columns) const;
|
|
|
|
bool isGranted(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const Strings & columns) const;
|
|
|
|
bool isGranted(const AccessRightsElement & element) const;
|
|
|
|
bool isGranted(const AccessRightsElements & elements) const;
|
|
|
|
|
|
|
|
bool hasGrantOption(const AccessFlags & flags) const;
|
|
|
|
bool hasGrantOption(const AccessFlags & flags, const std::string_view & database) const;
|
|
|
|
bool hasGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table) const;
|
|
|
|
bool hasGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::string_view & column) const;
|
|
|
|
bool hasGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const std::vector<std::string_view> & columns) const;
|
|
|
|
bool hasGrantOption(const AccessFlags & flags, const std::string_view & database, const std::string_view & table, const Strings & columns) const;
|
|
|
|
bool hasGrantOption(const AccessRightsElement & element) const;
|
|
|
|
bool hasGrantOption(const AccessRightsElements & elements) const;
|
|
|
|
|
2020-03-07 17:37:38 +00:00
|
|
|
/// Checks if a specified role is granted with admin option, and throws an exception if not.
|
|
|
|
void checkAdminOption(const UUID & role_id) const;
|
2020-07-02 00:09:57 +00:00
|
|
|
void checkAdminOption(const UUID & role_id, const String & role_name) const;
|
|
|
|
void checkAdminOption(const UUID & role_id, const std::unordered_map<UUID, String> & names_of_roles) const;
|
|
|
|
void checkAdminOption(const std::vector<UUID> & role_ids) const;
|
|
|
|
void checkAdminOption(const std::vector<UUID> & role_ids, const Strings & names_of_roles) const;
|
|
|
|
void checkAdminOption(const std::vector<UUID> & role_ids, const std::unordered_map<UUID, String> & names_of_roles) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2021-02-26 22:37:00 +00:00
|
|
|
/// Checks if a specified role is granted with admin option, and returns false if not.
|
2020-10-12 18:29:02 +00:00
|
|
|
bool hasAdminOption(const UUID & role_id) const;
|
|
|
|
bool hasAdminOption(const UUID & role_id, const String & role_name) const;
|
|
|
|
bool hasAdminOption(const UUID & role_id, const std::unordered_map<UUID, String> & names_of_roles) const;
|
|
|
|
bool hasAdminOption(const std::vector<UUID> & role_ids) const;
|
|
|
|
bool hasAdminOption(const std::vector<UUID> & role_ids, const Strings & names_of_roles) const;
|
|
|
|
bool hasAdminOption(const std::vector<UUID> & role_ids, const std::unordered_map<UUID, String> & names_of_roles) const;
|
|
|
|
|
2020-04-29 19:35:56 +00:00
|
|
|
/// Makes an instance of ContextAccess which provides full access to everything
|
|
|
|
/// without any limitations. This is used for the global context.
|
2020-03-07 17:37:38 +00:00
|
|
|
static std::shared_ptr<const ContextAccess> getFullAccess();
|
|
|
|
|
|
|
|
private:
|
2021-11-02 11:06:20 +00:00
|
|
|
friend class AccessControl;
|
2020-03-07 17:37:38 +00:00
|
|
|
ContextAccess() {}
|
2021-11-02 11:06:20 +00:00
|
|
|
ContextAccess(const AccessControl & access_control_, const Params & params_);
|
2020-03-07 17:37:38 +00:00
|
|
|
|
|
|
|
void setUser(const UserPtr & user_) const;
|
|
|
|
void setRolesInfo(const std::shared_ptr<const EnabledRolesInfo> & roles_info_) const;
|
2020-03-04 22:27:03 +00:00
|
|
|
void setSettingsAndConstraints() const;
|
2020-07-02 00:09:57 +00:00
|
|
|
void calculateAccessRights() const;
|
2020-06-20 22:44:52 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied, bool grant_option>
|
|
|
|
bool checkAccessImpl(const AccessFlags & flags) const;
|
2020-06-20 22:44:52 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied, bool grant_option, typename... Args>
|
|
|
|
bool checkAccessImpl(const AccessFlags & flags, const std::string_view & database, const Args &... args) const;
|
2020-06-20 22:44:52 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied, bool grant_option>
|
|
|
|
bool checkAccessImpl(const AccessRightsElement & element) const;
|
2020-06-20 22:44:52 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied, bool grant_option>
|
|
|
|
bool checkAccessImpl(const AccessRightsElements & elements) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied, bool grant_option, typename... Args>
|
2021-02-26 22:37:00 +00:00
|
|
|
bool checkAccessImplHelper(const AccessFlags & flags, const Args &... args) const;
|
|
|
|
|
|
|
|
template <bool throw_if_denied, bool grant_option>
|
|
|
|
bool checkAccessImplHelper(const AccessRightsElement & element) const;
|
2020-04-10 22:23:27 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const UUID & role_id) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const UUID & role_id, const String & role_name) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const UUID & role_id, const std::unordered_map<UUID, String> & names_of_roles) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const std::vector<UUID> & role_ids) const;
|
2020-04-10 22:23:27 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const std::vector<UUID> & role_ids, const Strings & names_of_roles) const;
|
2020-03-07 17:37:38 +00:00
|
|
|
|
2020-12-08 14:24:32 +00:00
|
|
|
template <bool throw_if_denied>
|
|
|
|
bool checkAdminOptionImpl(const std::vector<UUID> & role_ids, const std::unordered_map<UUID, String> & names_of_roles) const;
|
|
|
|
|
|
|
|
template <bool throw_if_denied, typename Container, typename GetNameFunction>
|
2021-02-26 22:37:00 +00:00
|
|
|
bool checkAdminOptionImplHelper(const Container & role_ids, const GetNameFunction & get_name_function) const;
|
2020-07-02 00:09:57 +00:00
|
|
|
|
2021-11-02 11:06:20 +00:00
|
|
|
const AccessControl * access_control = nullptr;
|
2020-03-07 17:37:38 +00:00
|
|
|
const Params params;
|
2020-12-08 14:24:32 +00:00
|
|
|
bool is_full_access = false;
|
2020-03-07 17:37:38 +00:00
|
|
|
mutable Poco::Logger * trace_log = nullptr;
|
|
|
|
mutable UserPtr user;
|
|
|
|
mutable String user_name;
|
2021-06-15 19:55:21 +00:00
|
|
|
mutable scope_guard subscription_for_user_change;
|
2020-03-07 17:37:38 +00:00
|
|
|
mutable std::shared_ptr<const EnabledRoles> enabled_roles;
|
2021-06-15 19:55:21 +00:00
|
|
|
mutable scope_guard subscription_for_roles_changes;
|
2020-03-07 17:37:38 +00:00
|
|
|
mutable std::shared_ptr<const EnabledRolesInfo> roles_info;
|
2020-06-20 22:44:52 +00:00
|
|
|
mutable std::shared_ptr<const AccessRights> access;
|
2020-12-08 14:24:32 +00:00
|
|
|
mutable std::shared_ptr<const AccessRights> access_with_implicit;
|
2020-03-07 17:37:38 +00:00
|
|
|
mutable std::shared_ptr<const EnabledRowPolicies> enabled_row_policies;
|
|
|
|
mutable std::shared_ptr<const EnabledQuota> enabled_quota;
|
2020-03-04 22:27:03 +00:00
|
|
|
mutable std::shared_ptr<const EnabledSettings> enabled_settings;
|
2020-03-07 17:37:38 +00:00
|
|
|
mutable std::mutex mutex;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|