mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +00:00
Add WITH IMPLICIT
, fix error with implicit grants
This commit is contained in:
parent
229ead5f91
commit
2a107e3429
@ -351,7 +351,7 @@ Shows privileges for a user.
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT]
|
||||
```
|
||||
|
||||
If user is not specified, the query returns privileges for the current user.
|
||||
|
@ -234,7 +234,7 @@ SHOW DICTIONARIES FROM db LIKE '%reg%' LIMIT 2
|
||||
### Синтаксис {#show-grants-syntax}
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT]
|
||||
```
|
||||
|
||||
Если пользователь не задан, запрос возвращает привилегии текущего пользователя.
|
||||
|
@ -110,7 +110,7 @@ SHOW DICTIONARIES FROM db LIKE '%reg%' LIMIT 2
|
||||
### 语法 {#show-grants-syntax}
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT]
|
||||
```
|
||||
|
||||
如果未指定用户,输出当前用户的权限
|
||||
|
@ -1155,9 +1155,6 @@ private:
|
||||
|
||||
calculateMinMaxFlags();
|
||||
|
||||
if (!isLeaf())
|
||||
return;
|
||||
|
||||
auto new_flags = function(flags, min_flags_with_children, max_flags_with_children, level, grant_option);
|
||||
|
||||
if (new_flags != flags)
|
||||
|
@ -64,7 +64,27 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
AccessRights addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control)
|
||||
std::array<UUID, 1> to_array(const UUID & id)
|
||||
{
|
||||
std::array<UUID, 1> ids;
|
||||
ids[0] = id;
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// Helper for using in templates.
|
||||
std::string_view getDatabase() { return {}; }
|
||||
|
||||
template <typename... OtherArgs>
|
||||
std::string_view getDatabase(std::string_view arg1, const OtherArgs &...) { return arg1; }
|
||||
|
||||
std::string_view getTableEngine() { return {}; }
|
||||
|
||||
template <typename... OtherArgs>
|
||||
std::string_view getTableEngine(std::string_view arg1, const OtherArgs &...) { return arg1; }
|
||||
}
|
||||
|
||||
|
||||
AccessRights ContextAccess::addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control)
|
||||
{
|
||||
AccessFlags max_flags;
|
||||
|
||||
@ -254,26 +274,6 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
std::array<UUID, 1> to_array(const UUID & id)
|
||||
{
|
||||
std::array<UUID, 1> ids;
|
||||
ids[0] = id;
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// Helper for using in templates.
|
||||
std::string_view getDatabase() { return {}; }
|
||||
|
||||
template <typename... OtherArgs>
|
||||
std::string_view getDatabase(std::string_view arg1, const OtherArgs &...) { return arg1; }
|
||||
|
||||
std::string_view getTableEngine() { return {}; }
|
||||
|
||||
template <typename... OtherArgs>
|
||||
std::string_view getTableEngine(std::string_view arg1, const OtherArgs &...) { return arg1; }
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<const ContextAccess> ContextAccess::fromContext(const ContextPtr & context)
|
||||
{
|
||||
return ContextAccessWrapper::fromContext(context)->getAccess();
|
||||
|
@ -133,6 +133,8 @@ public:
|
||||
/// Checks if grantees are allowed for the current user, throws an exception if not.
|
||||
void checkGranteesAreAllowed(const std::vector<UUID> & grantee_ids) const;
|
||||
|
||||
static AccessRights addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control);
|
||||
|
||||
ContextAccess(const AccessControl & access_control_, const Params & params_);
|
||||
~ContextAccess();
|
||||
|
||||
|
@ -32,7 +32,8 @@ namespace
|
||||
ASTs getGrantQueriesImpl(
|
||||
const T & grantee,
|
||||
const AccessControl * access_control /* not used if attach_mode == true */,
|
||||
bool attach_mode = false)
|
||||
bool attach_mode = false,
|
||||
bool with_implicit = false)
|
||||
{
|
||||
ASTs res;
|
||||
|
||||
@ -41,7 +42,13 @@ namespace
|
||||
|
||||
std::shared_ptr<ASTGrantQuery> current_query = nullptr;
|
||||
|
||||
for (const auto & element : grantee.access.getElements())
|
||||
AccessRightsElements elements;
|
||||
if (with_implicit)
|
||||
elements = ContextAccess::addImplicitAccessRights(grantee.access, *access_control).getElements();
|
||||
else
|
||||
elements = grantee.access.getElements();
|
||||
|
||||
for (const auto & element : elements)
|
||||
{
|
||||
if (element.empty())
|
||||
continue;
|
||||
@ -89,12 +96,13 @@ namespace
|
||||
ASTs getGrantQueriesImpl(
|
||||
const IAccessEntity & entity,
|
||||
const AccessControl * access_control /* not used if attach_mode == true */,
|
||||
bool attach_mode = false)
|
||||
bool attach_mode = false,
|
||||
bool with_implicit = false)
|
||||
{
|
||||
if (const User * user = typeid_cast<const User *>(&entity))
|
||||
return getGrantQueriesImpl(*user, access_control, attach_mode);
|
||||
return getGrantQueriesImpl(*user, access_control, attach_mode, with_implicit);
|
||||
if (const Role * role = typeid_cast<const Role *>(&entity))
|
||||
return getGrantQueriesImpl(*role, access_control, attach_mode);
|
||||
return getGrantQueriesImpl(*role, access_control, attach_mode, with_implicit);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "{} is expected to be user or role", entity.formatTypeWithName());
|
||||
}
|
||||
|
||||
@ -180,23 +188,24 @@ ASTs InterpreterShowGrantsQuery::getGrantQueries() const
|
||||
auto entities = getEntities();
|
||||
const auto & access_control = getContext()->getAccessControl();
|
||||
|
||||
const auto & show_query = query_ptr->as<const ASTShowGrantsQuery &>();
|
||||
ASTs grant_queries;
|
||||
for (const auto & entity : entities)
|
||||
boost::range::push_back(grant_queries, getGrantQueries(*entity, access_control));
|
||||
boost::range::push_back(grant_queries, getGrantQueries(*entity, access_control, show_query.with_implicit));
|
||||
|
||||
return grant_queries;
|
||||
}
|
||||
|
||||
|
||||
ASTs InterpreterShowGrantsQuery::getGrantQueries(const IAccessEntity & user_or_role, const AccessControl & access_control)
|
||||
ASTs InterpreterShowGrantsQuery::getGrantQueries(const IAccessEntity & user_or_role, const AccessControl & access_control, bool with_implicit)
|
||||
{
|
||||
return getGrantQueriesImpl(user_or_role, &access_control, false);
|
||||
return getGrantQueriesImpl(user_or_role, &access_control, false, with_implicit);
|
||||
}
|
||||
|
||||
|
||||
ASTs InterpreterShowGrantsQuery::getAttachGrantQueries(const IAccessEntity & user_or_role)
|
||||
{
|
||||
return getGrantQueriesImpl(user_or_role, nullptr, true);
|
||||
return getGrantQueriesImpl(user_or_role, nullptr, true, false);
|
||||
}
|
||||
|
||||
void registerInterpreterShowGrantsQuery(InterpreterFactory & factory)
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
|
||||
BlockIO execute() override;
|
||||
|
||||
static ASTs getGrantQueries(const IAccessEntity & user_or_role, const AccessControl & access_control);
|
||||
static ASTs getGrantQueries(const IAccessEntity & user_or_role, const AccessControl & access_control, bool with_implicit = false);
|
||||
static ASTs getAttachGrantQueries(const IAccessEntity & user_or_role);
|
||||
|
||||
bool ignoreQuota() const override { return true; }
|
||||
|
@ -38,5 +38,11 @@ void ASTShowGrantsQuery::formatQueryImpl(const FormatSettings & settings, Format
|
||||
<< (settings.hilite ? hilite_none : "");
|
||||
for_roles->format(settings);
|
||||
}
|
||||
|
||||
if (with_implicit)
|
||||
{
|
||||
settings.ostr << (settings.hilite ? hilite_keyword : "") << " WITH IMPLICIT"
|
||||
<< (settings.hilite ? hilite_none : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ namespace DB
|
||||
{
|
||||
class ASTRolesOrUsersSet;
|
||||
|
||||
/** SHOW GRANTS [FOR user_name]
|
||||
/** SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT]
|
||||
*/
|
||||
class ASTShowGrantsQuery : public ASTQueryWithOutput
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<ASTRolesOrUsersSet> for_roles;
|
||||
bool with_implicit = false;
|
||||
|
||||
String getID(char) const override;
|
||||
ASTPtr clone() const override;
|
||||
|
@ -31,8 +31,13 @@ bool ParserShowGrantsQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
for_roles->current_user = true;
|
||||
}
|
||||
|
||||
bool with_implicit = false;
|
||||
if (ParserKeyword{Keyword::WITH_IMPLICIT}.ignore(pos, expected))
|
||||
with_implicit = true;
|
||||
|
||||
auto query = std::make_shared<ASTShowGrantsQuery>();
|
||||
query->for_roles = std::move(for_roles);
|
||||
query->with_implicit = with_implicit;
|
||||
node = query;
|
||||
|
||||
return true;
|
||||
|
@ -530,6 +530,7 @@ namespace DB
|
||||
MR_MACROS(WITH_NAME, "WITH NAME") \
|
||||
MR_MACROS(WITH_REPLACE_OPTION, "WITH REPLACE OPTION") \
|
||||
MR_MACROS(WITH_TIES, "WITH TIES") \
|
||||
MR_MACROS(WITH_IMPLICIT, "WITH IMPLICIT") \
|
||||
MR_MACROS(WITH, "WITH") \
|
||||
MR_MACROS(RECURSIVE, "RECURSIVE") \
|
||||
MR_MACROS(WK, "WK") \
|
||||
|
@ -0,0 +1,29 @@
|
||||
Empty grants
|
||||
GRANT SOURCES ON *.*
|
||||
GRANT TABLE ENGINE ON *
|
||||
GRANT SELECT ON system.aggregate_function_combinators
|
||||
GRANT SELECT ON system.collations
|
||||
GRANT SELECT ON system.columns
|
||||
GRANT SELECT ON system.contributors
|
||||
GRANT SELECT ON system.current_roles
|
||||
GRANT SELECT ON system.data_type_families
|
||||
GRANT SELECT ON system.database_engines
|
||||
GRANT SELECT ON system.databases
|
||||
GRANT SELECT ON system.enabled_roles
|
||||
GRANT SELECT ON system.formats
|
||||
GRANT SELECT ON system.functions
|
||||
GRANT SELECT ON system.licenses
|
||||
GRANT SELECT ON system.one
|
||||
GRANT SELECT ON system.privileges
|
||||
GRANT SELECT ON system.quota_usage
|
||||
GRANT SELECT ON system.settings
|
||||
GRANT SELECT ON system.table_engines
|
||||
GRANT SELECT ON system.table_functions
|
||||
GRANT SELECT ON system.tables
|
||||
GRANT SELECT ON system.time_zones
|
||||
Revoke grants
|
||||
GRANT SHOW DATABASES, SHOW TABLES, SHOW COLUMNS, SELECT, SOURCES ON *.*
|
||||
GRANT TABLE ENGINE ON *
|
||||
REVOKE SHOW TABLES, SHOW COLUMNS, SELECT ON test_03247.`table`
|
||||
OK
|
||||
0
|
25
tests/queries/0_stateless/03247_show_grants_with_implicit.sh
Executable file
25
tests/queries/0_stateless/03247_show_grants_with_implicit.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
user="user03247_${CLICKHOUSE_DATABASE}_$RANDOM"
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "DROP USER IF EXISTS $user;";
|
||||
${CLICKHOUSE_CLIENT} --query "CREATE USER $user;";
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "GRANT SOURCES ON *.* TO $user;";
|
||||
|
||||
echo "Empty grants";
|
||||
${CLICKHOUSE_CLIENT} --query "SHOW GRANTS FOR $user WITH IMPLICIT;" | sed 's/ TO.*//';
|
||||
|
||||
echo "Revoke grants";
|
||||
${CLICKHOUSE_CLIENT} --query "GRANT SELECT ON *.* TO $user ;";
|
||||
${CLICKHOUSE_CLIENT} --query "REVOKE SELECT ON test_03247.table FROM $user;";
|
||||
${CLICKHOUSE_CLIENT} --query "SHOW GRANTS FOR $user WITH IMPLICIT;" | sed 's/ TO.*//' | sed 's/ FROM.*//';
|
||||
|
||||
(( $(${CLICKHOUSE_CLIENT} --user $user --query "EXISTS test_03247.table;" 2>&1 | grep -c "Not enough privileges") >= 1 )) && echo "OK" || echo "UNEXPECTED";
|
||||
${CLICKHOUSE_CLIENT} --query "EXISTS test_03247.table2;" --user $user;
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "DROP USER IF EXISTS $user;";
|
Loading…
Reference in New Issue
Block a user