diff --git a/src/Access/AccessType.h b/src/Access/AccessType.h index 9aa9e29e026..e242000635d 100644 --- a/src/Access/AccessType.h +++ b/src/Access/AccessType.h @@ -91,22 +91,29 @@ enum class AccessType M(KILL_QUERY, "", GLOBAL, ALL) /* allows to kill a query started by another user (anyone can kill his own queries) */\ \ - M(CREATE_USER, "", GLOBAL, ALL) \ - M(ALTER_USER, "", GLOBAL, ALL) \ - M(DROP_USER, "", GLOBAL, ALL) \ - M(CREATE_ROLE, "", GLOBAL, ALL) \ - M(ALTER_ROLE, "", GLOBAL, ALL) \ - M(DROP_ROLE, "", GLOBAL, ALL) \ - M(ROLE_ADMIN, "", GLOBAL, ALL) /* allows to grant and revoke the roles which are not granted to the current user with admin option */\ - M(CREATE_ROW_POLICY, "CREATE POLICY", GLOBAL, ALL) \ - M(ALTER_ROW_POLICY, "ALTER POLICY", GLOBAL, ALL) \ - M(DROP_ROW_POLICY, "DROP POLICY", GLOBAL, ALL) \ - M(CREATE_QUOTA, "", GLOBAL, ALL) \ - M(ALTER_QUOTA, "", GLOBAL, ALL) \ - M(DROP_QUOTA, "", GLOBAL, ALL) \ - M(CREATE_SETTINGS_PROFILE, "CREATE PROFILE", GLOBAL, ALL) \ - M(ALTER_SETTINGS_PROFILE, "ALTER PROFILE", GLOBAL, ALL) \ - M(DROP_SETTINGS_PROFILE, "DROP PROFILE", GLOBAL, ALL) \ + M(CREATE_USER, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(ALTER_USER, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(DROP_USER, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(CREATE_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(ALTER_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(DROP_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(ROLE_ADMIN, "", GLOBAL, ACCESS_MANAGEMENT) /* allows to grant and revoke the roles which are not granted to the current user with admin option */\ + M(CREATE_ROW_POLICY, "CREATE POLICY", GLOBAL, ACCESS_MANAGEMENT) \ + M(ALTER_ROW_POLICY, "ALTER POLICY", GLOBAL, ACCESS_MANAGEMENT) \ + M(DROP_ROW_POLICY, "DROP POLICY", GLOBAL, ACCESS_MANAGEMENT) \ + M(CREATE_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(ALTER_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(DROP_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \ + M(CREATE_SETTINGS_PROFILE, "CREATE PROFILE", GLOBAL, ACCESS_MANAGEMENT) \ + M(ALTER_SETTINGS_PROFILE, "ALTER PROFILE", GLOBAL, ACCESS_MANAGEMENT) \ + M(DROP_SETTINGS_PROFILE, "DROP PROFILE", GLOBAL, ACCESS_MANAGEMENT) \ + M(SHOW_USERS, "SHOW CREATE USER", GLOBAL, SHOW_ACCESS) \ + M(SHOW_ROLES, "SHOW CREATE ROLE", GLOBAL, SHOW_ACCESS) \ + M(SHOW_ROW_POLICIES, "SHOW POLICIES, SHOW CREATE ROW POLICY, SHOW CREATE POLICY", GLOBAL, SHOW_ACCESS) \ + M(SHOW_QUOTAS, "SHOW CREATE QUOTA", GLOBAL, SHOW_ACCESS) \ + M(SHOW_SETTINGS_PROFILES, "SHOW PROFILES, SHOW CREATE SETTINGS PROFILE, SHOW CREATE PROFILE", GLOBAL, SHOW_ACCESS) \ + M(SHOW_ACCESS, "", GROUP, ACCESS_MANAGEMENT) \ + M(ACCESS_MANAGEMENT, "", GROUP, ALL) \ \ M(SYSTEM_SHUTDOWN, "SYSTEM KILL, SHUTDOWN", GLOBAL, SYSTEM) \ M(SYSTEM_DROP_DNS_CACHE, "SYSTEM DROP DNS, DROP DNS CACHE, DROP DNS", GLOBAL, SYSTEM_DROP_CACHE) \ diff --git a/src/Access/ContextAccess.cpp b/src/Access/ContextAccess.cpp index 812dc822e63..d6c7abfd4ba 100644 --- a/src/Access/ContextAccess.cpp +++ b/src/Access/ContextAccess.cpp @@ -409,14 +409,8 @@ boost::shared_ptr ContextAccess::calculateResultAccess(bool static const AccessFlags table_and_dictionary_ddl = table_ddl | dictionary_ddl; static const AccessFlags write_table_access = AccessType::INSERT | AccessType::OPTIMIZE; - static const AccessFlags all_dcl = AccessType::CREATE_USER | AccessType::ALTER_USER | AccessType::DROP_USER - | AccessType::CREATE_ROLE | AccessType::ALTER_ROLE | AccessType::DROP_ROLE | AccessType::ROLE_ADMIN - | AccessType::CREATE_ROW_POLICY | AccessType::ALTER_ROW_POLICY | AccessType::DROP_ROW_POLICY - | AccessType::CREATE_SETTINGS_PROFILE | AccessType::ALTER_SETTINGS_PROFILE | AccessType::DROP_SETTINGS_PROFILE - | AccessType::CREATE_QUOTA | AccessType::ALTER_QUOTA | AccessType::DROP_QUOTA; - if (readonly_) - merged_access->revoke(write_table_access | all_dcl | table_and_dictionary_ddl | AccessType::SYSTEM | AccessType::KILL_QUERY); + merged_access->revoke(write_table_access | table_and_dictionary_ddl | AccessType::SYSTEM | AccessType::KILL_QUERY | AccessType::ACCESS_MANAGEMENT); if (readonly_ == 1) { diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp index 13102528108..0842839dec8 100644 --- a/src/Access/UsersConfigAccessStorage.cpp +++ b/src/Access/UsersConfigAccessStorage.cpp @@ -168,7 +168,14 @@ namespace user->access.grant(AccessFlags::allDictionaryFlags(), IDictionary::NO_DATABASE_TAG, dictionary); } - user->access_with_grant_option = user->access; + user->access_with_grant_option = user->access; /// By default the user can grant everything he has. + + bool access_management = config.getBool(user_config + ".access_management", false); + if (!access_management) + { + user->access.revoke(AccessType::ACCESS_MANAGEMENT); + user->access_with_grant_option.clear(); + } return user; } diff --git a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp index 52126b0507e..d2f435106a8 100644 --- a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp +++ b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp @@ -256,6 +256,7 @@ BlockInputStreamPtr InterpreterShowCreateAccessEntityQuery::executeImpl() ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const ASTShowCreateAccessEntityQuery & show_query) const { const auto & access_control = context.getAccessControlManager(); + context.checkAccess(getRequiredAccess()); if (show_query.current_user) { @@ -281,6 +282,22 @@ ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const ASTShowCreat } +AccessRightsElements InterpreterShowCreateAccessEntityQuery::getRequiredAccess() const +{ + const auto & show_query = query_ptr->as(); + AccessRightsElements res; + switch (show_query.kind) + { + case Kind::USER: res.emplace_back(AccessType::SHOW_USERS); break; + case Kind::ROLE: res.emplace_back(AccessType::SHOW_ROLES); break; + case Kind::ROW_POLICY: res.emplace_back(AccessType::SHOW_ROW_POLICIES); break; + case Kind::SETTINGS_PROFILE: res.emplace_back(AccessType::SHOW_SETTINGS_PROFILES); break; + case Kind::QUOTA: res.emplace_back(AccessType::SHOW_QUOTAS); break; + } + return res; +} + + ASTPtr InterpreterShowCreateAccessEntityQuery::getAttachQuery(const IAccessEntity & entity) { return getCreateQueryImpl(entity, nullptr, true); diff --git a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h index 92025bedb6c..0183c59766f 100644 --- a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h +++ b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h @@ -9,6 +9,7 @@ namespace DB { class Context; class ASTShowCreateAccessEntityQuery; +class AccessRightsElements; struct IAccessEntity; @@ -30,6 +31,7 @@ public: private: BlockInputStreamPtr executeImpl(); ASTPtr getCreateQuery(const ASTShowCreateAccessEntityQuery & show_query) const; + AccessRightsElements getRequiredAccess() const; ASTPtr query_ptr; const Context & context; diff --git a/src/Storages/System/StorageSystemQuotaUsage.cpp b/src/Storages/System/StorageSystemQuotaUsage.cpp index 53afb1d563a..1f943d02446 100644 --- a/src/Storages/System/StorageSystemQuotaUsage.cpp +++ b/src/Storages/System/StorageSystemQuotaUsage.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -40,7 +41,9 @@ NamesAndTypesList StorageSystemQuotaUsage::getNamesAndTypes() void StorageSystemQuotaUsage::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const { + context.checkAccess(AccessType::SHOW_QUOTAS); const auto & access_control = context.getAccessControlManager(); + for (const auto & info : access_control.getQuotaUsageInfo()) { for (const auto & interval : info.intervals) diff --git a/src/Storages/System/StorageSystemQuotas.cpp b/src/Storages/System/StorageSystemQuotas.cpp index 228339ea305..a22bb11bbc3 100644 --- a/src/Storages/System/StorageSystemQuotas.cpp +++ b/src/Storages/System/StorageSystemQuotas.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -54,6 +55,8 @@ NamesAndTypesList StorageSystemQuotas::getNamesAndTypes() void StorageSystemQuotas::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const { + context.checkAccess(AccessType::SHOW_QUOTAS); + size_t i = 0; auto & name_column = *res_columns[i++]; auto & id_column = *res_columns[i++]; diff --git a/src/Storages/System/StorageSystemRowPolicies.cpp b/src/Storages/System/StorageSystemRowPolicies.cpp index bd302cba3cf..12221cc52de 100644 --- a/src/Storages/System/StorageSystemRowPolicies.cpp +++ b/src/Storages/System/StorageSystemRowPolicies.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -33,6 +34,7 @@ NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes() void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const { + context.checkAccess(AccessType::SHOW_ROW_POLICIES); const auto & access_control = context.getAccessControlManager(); std::vector ids = access_control.findAll();