Revert "[WIP] New row policies"

This commit is contained in:
Alexey Milovidov 2022-03-21 08:41:33 +03:00 committed by GitHub
parent cf6c4e4e56
commit 0ce4696c49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 229 additions and 570 deletions

View File

@ -28,8 +28,6 @@
#include <Parsers/Access/ParserCreateSettingsProfileQuery.h> #include <Parsers/Access/ParserCreateSettingsProfileQuery.h>
#include <Parsers/Access/ParserCreateUserQuery.h> #include <Parsers/Access/ParserCreateUserQuery.h>
#include <Parsers/Access/ParserGrantQuery.h> #include <Parsers/Access/ParserGrantQuery.h>
#include <Parsers/ASTSetQuery.h>
#include <Parsers/ParserSetQuery.h>
#include <Parsers/formatAST.h> #include <Parsers/formatAST.h>
#include <Parsers/parseQuery.h> #include <Parsers/parseQuery.h>
#include <boost/range/algorithm/copy.hpp> #include <boost/range/algorithm/copy.hpp>
@ -40,16 +38,10 @@ namespace DB
namespace ErrorCodes namespace ErrorCodes
{ {
extern const int INCORRECT_ACCESS_ENTITY_DEFINITION; extern const int INCORRECT_ACCESS_ENTITY_DEFINITION;
extern const int RBAC_VERSION_IS_TOO_NEW;
} }
extern const UInt64 RBAC_INITIAL_VERSION;
extern const UInt64 RBAC_LATEST_VERSION;
namespace namespace
{ {
constexpr const char RBAC_VERSION_SETTING_NAME[] = "rbac_version";
/// Special parser for the 'ATTACH access entity' queries. /// Special parser for the 'ATTACH access entity' queries.
class ParserAttachAccessEntity : public IParserBase class ParserAttachAccessEntity : public IParserBase
{ {
@ -64,7 +56,6 @@ namespace
ParserCreateQuotaQuery create_quota_p; ParserCreateQuotaQuery create_quota_p;
ParserCreateSettingsProfileQuery create_profile_p; ParserCreateSettingsProfileQuery create_profile_p;
ParserGrantQuery grant_p; ParserGrantQuery grant_p;
ParserSetQuery set_p;
create_user_p.useAttachMode(); create_user_p.useAttachMode();
create_role_p.useAttachMode(); create_role_p.useAttachMode();
@ -75,8 +66,7 @@ namespace
return create_user_p.parse(pos, node, expected) || create_role_p.parse(pos, node, expected) return create_user_p.parse(pos, node, expected) || create_role_p.parse(pos, node, expected)
|| create_policy_p.parse(pos, node, expected) || create_quota_p.parse(pos, node, expected) || create_policy_p.parse(pos, node, expected) || create_quota_p.parse(pos, node, expected)
|| create_profile_p.parse(pos, node, expected) || grant_p.parse(pos, node, expected) || create_profile_p.parse(pos, node, expected) || grant_p.parse(pos, node, expected);
|| set_p.parse(pos, node, expected);
} }
}; };
@ -85,15 +75,8 @@ namespace
String serializeAccessEntity(const IAccessEntity & entity) String serializeAccessEntity(const IAccessEntity & entity)
{ {
ASTs queries;
{
/// Prepend the list with "SET rbac_version = ..." query.
auto set_rbac_version_query = std::make_shared<ASTSetQuery>();
set_rbac_version_query->changes.emplace_back(RBAC_VERSION_SETTING_NAME, RBAC_LATEST_VERSION);
queries.push_back(set_rbac_version_query);
}
/// Build list of ATTACH queries. /// Build list of ATTACH queries.
ASTs queries;
queries.push_back(InterpreterShowCreateAccessEntityQuery::getAttachQuery(entity)); queries.push_back(InterpreterShowCreateAccessEntityQuery::getAttachQuery(entity));
if ((entity.getType() == AccessEntityType::USER) || (entity.getType() == AccessEntityType::ROLE)) if ((entity.getType() == AccessEntityType::USER) || (entity.getType() == AccessEntityType::ROLE))
boost::range::push_back(queries, InterpreterShowGrantsQuery::getAttachGrantQueries(entity)); boost::range::push_back(queries, InterpreterShowGrantsQuery::getAttachGrantQueries(entity));
@ -122,12 +105,6 @@ AccessEntityPtr deserializeAccessEntityImpl(const String & definition)
++pos; ++pos;
} }
/// Number of queries interpreted.
size_t query_index = 0;
/// If there is no "SET rbac_version = ..." query we assume that it's the initial version.
UInt64 rbac_version = RBAC_INITIAL_VERSION;
/// Interpret the AST to build an access entity. /// Interpret the AST to build an access entity.
std::shared_ptr<User> user; std::shared_ptr<User> user;
std::shared_ptr<Role> role; std::shared_ptr<Role> role;
@ -138,24 +115,12 @@ AccessEntityPtr deserializeAccessEntityImpl(const String & definition)
for (const auto & query : queries) for (const auto & query : queries)
{ {
if (auto * set_query = query->as<ASTSetQuery>()) if (auto * create_user_query = query->as<ASTCreateUserQuery>())
{
if ((set_query->changes.size() != 1) || (set_query->changes[0].name != RBAC_VERSION_SETTING_NAME))
throw Exception(ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION, "SET query in this file is only allowed to set {}", RBAC_VERSION_SETTING_NAME);
if (query_index != 0)
throw Exception(ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION, "SET {} should be the first query in the file", RBAC_VERSION_SETTING_NAME);
rbac_version = set_query->changes[0].value.safeGet<UInt64>();
if (rbac_version < RBAC_INITIAL_VERSION)
throw Exception(ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION, "{} must be >= {}", RBAC_VERSION_SETTING_NAME, RBAC_INITIAL_VERSION);
if (rbac_version > RBAC_LATEST_VERSION)
throw Exception(ErrorCodes::RBAC_VERSION_IS_TOO_NEW, "{} must be <= {}, {} {} is too new", RBAC_VERSION_SETTING_NAME, RBAC_LATEST_VERSION, RBAC_VERSION_SETTING_NAME, rbac_version);
}
else if (auto * create_user_query = query->as<ASTCreateUserQuery>())
{ {
if (res) if (res)
throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION);
res = user = std::make_unique<User>(); res = user = std::make_unique<User>();
InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query); InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query, /* allow_no_password = */ true, /* allow_plaintext_password = */ true);
} }
else if (auto * create_role_query = query->as<ASTCreateRoleQuery>()) else if (auto * create_role_query = query->as<ASTCreateRoleQuery>())
{ {
@ -169,7 +134,7 @@ AccessEntityPtr deserializeAccessEntityImpl(const String & definition)
if (res) if (res)
throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION);
res = policy = std::make_unique<RowPolicy>(); res = policy = std::make_unique<RowPolicy>();
InterpreterCreateRowPolicyQuery::updateRowPolicyFromQuery(*policy, *create_policy_query, rbac_version); InterpreterCreateRowPolicyQuery::updateRowPolicyFromQuery(*policy, *create_policy_query);
} }
else if (auto * create_quota_query = query->as<ASTCreateQuotaQuery>()) else if (auto * create_quota_query = query->as<ASTCreateQuotaQuery>())
{ {
@ -196,8 +161,6 @@ AccessEntityPtr deserializeAccessEntityImpl(const String & definition)
} }
else else
throw Exception("No interpreter found for query " + query->getID(), ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); throw Exception("No interpreter found for query " + query->getID(), ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION);
++query_index;
} }
if (!res) if (!res)

View File

@ -78,40 +78,4 @@ const RowPolicyFilterTypeInfo & RowPolicyFilterTypeInfo::get(RowPolicyFilterType
throw Exception("Unknown type: " + std::to_string(static_cast<size_t>(type_)), ErrorCodes::LOGICAL_ERROR); throw Exception("Unknown type: " + std::to_string(static_cast<size_t>(type_)), ErrorCodes::LOGICAL_ERROR);
} }
String toString(RowPolicyKind type)
{
return RowPolicyKindInfo::get(type).raw_name;
}
const RowPolicyKindInfo & RowPolicyKindInfo::get(RowPolicyKind kind_)
{
static constexpr auto make_info = [](const char * raw_name_)
{
String nam = raw_name_;
boost::to_lower(nam);
return RowPolicyKindInfo{raw_name_, std::move(nam)};
};
switch (kind_)
{
case RowPolicyKind::PERMISSIVE:
{
static const auto info = make_info("PERMISSIVE");
return info;
}
case RowPolicyKind::RESTRICTIVE:
{
static const auto info = make_info("RESTRICTIVE");
return info;
}
case RowPolicyKind::SIMPLE:
{
static const auto info = make_info("SIMPLE");
return info;
}
case RowPolicyKind::MAX: break;
}
throw Exception("Unknown kind: " + std::to_string(static_cast<size_t>(kind_)), ErrorCodes::LOGICAL_ERROR);
}
} }

View File

@ -54,26 +54,4 @@ struct RowPolicyFilterTypeInfo
static const RowPolicyFilterTypeInfo & get(RowPolicyFilterType type); static const RowPolicyFilterTypeInfo & get(RowPolicyFilterType type);
}; };
/// Kinds of row policies. It affects how row policies are applied.
/// A row is only accessible if at least one of the permissive policies passes,
/// in addition to all the restrictive policies.
enum class RowPolicyKind
{
PERMISSIVE,
RESTRICTIVE,
SIMPLE,
MAX,
};
String toString(RowPolicyKind kind);
struct RowPolicyKindInfo
{
const char * const raw_name;
const String name; /// Lowercased with underscores, e.g. "permissive".
static const RowPolicyKindInfo & get(RowPolicyKind kind);
};
} }

View File

@ -1,17 +0,0 @@
#include <base/types.h>
namespace DB
{
extern const UInt64 RBAC_INITIAL_VERSION = 1;
/// rbac_version < 2:
/// row policies are permissive by default
///
/// rbac_version >= 2:
/// row policies are simple by default
extern const UInt64 RBAC_VERSION_ROW_POLICIES_ARE_SIMPLE_BY_DEFAULT = 2;
extern const UInt64 RBAC_LATEST_VERSION = 2;
}

View File

@ -55,7 +55,7 @@ bool RowPolicy::equal(const IAccessEntity & other) const
return false; return false;
const auto & other_policy = typeid_cast<const RowPolicy &>(other); const auto & other_policy = typeid_cast<const RowPolicy &>(other);
return (full_name == other_policy.full_name) && boost::range::equal(filters, other_policy.filters) return (full_name == other_policy.full_name) && boost::range::equal(filters, other_policy.filters)
&& (kind == other_policy.kind) && (to_roles == other_policy.to_roles); && restrictive == other_policy.restrictive && (to_roles == other_policy.to_roles);
} }
} }

View File

@ -29,9 +29,17 @@ struct RowPolicy : public IAccessEntity
/// for user or available for modification. /// for user or available for modification.
std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> filters; std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> filters;
/// Sets the kind of the policy, it affects how row policies are applied. /// Sets that the policy is permissive.
void setKind(RowPolicyKind kind_) { kind = kind_; } /// A row is only accessible if at least one of the permissive policies passes,
RowPolicyKind getKind() const { return kind; } /// in addition to all the restrictive policies.
void setPermissive(bool permissive_ = true) { setRestrictive(!permissive_); }
bool isPermissive() const { return !isRestrictive(); }
/// Sets that the policy is restrictive.
/// A row is only accessible if at least one of the permissive policies passes,
/// in addition to all the restrictive policies.
void setRestrictive(bool restrictive_ = true) { restrictive = restrictive_; }
bool isRestrictive() const { return restrictive; }
bool equal(const IAccessEntity & other) const override; bool equal(const IAccessEntity & other) const override;
std::shared_ptr<IAccessEntity> clone() const override { return cloneImpl<RowPolicy>(); } std::shared_ptr<IAccessEntity> clone() const override { return cloneImpl<RowPolicy>(); }
@ -45,7 +53,7 @@ private:
void setName(const String &) override; void setName(const String &) override;
RowPolicyName full_name; RowPolicyName full_name;
RowPolicyKind kind = RowPolicyKind::PERMISSIVE; bool restrictive = false;
}; };
using RowPolicyPtr = std::shared_ptr<const RowPolicy>; using RowPolicyPtr = std::shared_ptr<const RowPolicy>;

View File

@ -20,21 +20,18 @@ namespace
class FiltersMixer class FiltersMixer
{ {
public: public:
void add(const ASTPtr & filter, RowPolicyKind kind) void add(const ASTPtr & filter, bool is_restrictive)
{ {
if (kind == RowPolicyKind::PERMISSIVE) if (is_restrictive)
permissions.push_back(filter);
else if ((kind == RowPolicyKind::RESTRICTIVE) || (kind == RowPolicyKind::SIMPLE))
restrictions.push_back(filter); restrictions.push_back(filter);
if ((kind == RowPolicyKind::PERMISSIVE) || (kind == RowPolicyKind::RESTRICTIVE)) else
setUsePermissiveFilters(true); permissions.push_back(filter);
} }
ASTPtr getResult() && ASTPtr getResult() &&
{ {
/// Process permissive filters. /// Process permissive filters.
if (use_permissive_filters) restrictions.push_back(makeASTForLogicalOr(std::move(permissions)));
restrictions.push_back(makeASTForLogicalOr(std::move(permissions)));
/// Process restrictive filters. /// Process restrictive filters.
auto result = makeASTForLogicalAnd(std::move(restrictions)); auto result = makeASTForLogicalAnd(std::move(restrictions));
@ -46,17 +43,9 @@ namespace
return result; return result;
} }
/// If permissive filters are enabled then but no filters have been added then getResult() returns zero (i.e. no rows allowed).
/// It can happen if permissive or restrictive row policies have been added for some other users.
/// For example if the following is an only row policy for table1:
/// CREATE ROW POLICY policy1 ON table1 USING id=1 AS permissive TO user1
/// then user1 will see rows with id=1 and user2 will see no rows at all.
void setUsePermissiveFilters(bool use_permissive_filters_) { use_permissive_filters = use_permissive_filters_; }
private: private:
ASTs permissions; ASTs permissions;
ASTs restrictions; ASTs restrictions;
bool use_permissive_filters = false;
}; };
} }
@ -234,10 +223,8 @@ void RowPolicyCache::mixFiltersFor(EnabledRowPolicies & enabled)
key.filter_type = filter_type; key.filter_type = filter_type;
auto & mixer = mixers[key]; auto & mixer = mixers[key];
mixer.database_and_table_name = info.database_and_table_name; mixer.database_and_table_name = info.database_and_table_name;
if ((policy.getKind() == RowPolicyKind::PERMISSIVE) || (policy.getKind() == RowPolicyKind::RESTRICTIVE))
mixer.mixer.setUsePermissiveFilters(true);
if (match) if (match)
mixer.mixer.add(info.parsed_filters[filter_type_i], policy.getKind()); mixer.mixer.add(info.parsed_filters[filter_type_i], policy.isRestrictive());
} }
} }
} }

View File

@ -614,7 +614,6 @@
M(643, CANNOT_UNPACK_ARCHIVE) \ M(643, CANNOT_UNPACK_ARCHIVE) \
M(644, REMOTE_FS_OBJECT_CACHE_ERROR) \ M(644, REMOTE_FS_OBJECT_CACHE_ERROR) \
M(645, NUMBER_OF_DIMENSIONS_MISMATHED) \ M(645, NUMBER_OF_DIMENSIONS_MISMATHED) \
M(646, RBAC_VERSION_IS_TOO_NEW) \
\ \
M(999, KEEPER_EXCEPTION) \ M(999, KEEPER_EXCEPTION) \
M(1000, POCO_EXCEPTION) \ M(1000, POCO_EXCEPTION) \

View File

@ -693,8 +693,7 @@ class IColumn;
\ \
M(Bool, output_format_arrow_low_cardinality_as_dictionary, false, "Enable output LowCardinality type as Dictionary Arrow type", 0) \ M(Bool, output_format_arrow_low_cardinality_as_dictionary, false, "Enable output LowCardinality type as Dictionary Arrow type", 0) \
\ \
M(EnumComparingMode, format_capn_proto_enum_comparising_mode, FormatSettings::EnumComparingMode::BY_VALUES, "How to map ClickHouse Enum and CapnProto Enum", 0) \ M(EnumComparingMode, format_capn_proto_enum_comparising_mode, FormatSettings::EnumComparingMode::BY_VALUES, "How to map ClickHouse Enum and CapnProto Enum", 0)\
M(UInt64, rbac_version, 1, "RBAC version", 0)\
// End of FORMAT_FACTORY_SETTINGS // End of FORMAT_FACTORY_SETTINGS
// Please add settings non-related to formats into the COMMON_SETTINGS above. // Please add settings non-related to formats into the COMMON_SETTINGS above.

View File

@ -14,14 +14,11 @@
namespace DB namespace DB
{ {
extern const UInt64 RBAC_VERSION_ROW_POLICIES_ARE_SIMPLE_BY_DEFAULT;
namespace namespace
{ {
void updateRowPolicyFromQueryImpl( void updateRowPolicyFromQueryImpl(
RowPolicy & policy, RowPolicy & policy,
const ASTCreateRowPolicyQuery & query, const ASTCreateRowPolicyQuery & query,
UInt64 rbac_version,
const RowPolicyName & override_name, const RowPolicyName & override_name,
const std::optional<RolesOrUsersSet> & override_to_roles) const std::optional<RolesOrUsersSet> & override_to_roles)
{ {
@ -32,25 +29,16 @@ namespace
else if (query.names->full_names.size() == 1) else if (query.names->full_names.size() == 1)
policy.setFullName(query.names->full_names.front()); policy.setFullName(query.names->full_names.front());
std::optional<RowPolicyKind> new_kind = query.kind; if (query.is_restrictive)
if (!query.alter && !new_kind) policy.setRestrictive(*query.is_restrictive);
{
if (rbac_version < RBAC_VERSION_ROW_POLICIES_ARE_SIMPLE_BY_DEFAULT)
new_kind = RowPolicyKind::PERMISSIVE;
else
new_kind = RowPolicyKind::SIMPLE;
}
if (new_kind)
policy.setKind(*new_kind);
for (const auto & [filter_type, filter] : query.filters) for (const auto & [filter_type, filter] : query.filters)
policy.filters[static_cast<size_t>(filter_type)] = filter ? serializeAST(*filter) : String{}; policy.filters[static_cast<size_t>(filter_type)] = filter ? serializeAST(*filter) : String{};
if (override_to_roles) if (override_to_roles)
policy.to_roles = *override_to_roles; policy.to_roles = *override_to_roles;
else if (query.to_roles) else if (query.roles)
policy.to_roles = *query.to_roles; policy.to_roles = *query.roles;
} }
} }
@ -68,21 +56,20 @@ BlockIO InterpreterCreateRowPolicyQuery::execute()
assert(query.names->cluster.empty()); assert(query.names->cluster.empty());
auto & access_control = getContext()->getAccessControl(); auto & access_control = getContext()->getAccessControl();
UInt64 rbac_version = getContext()->getSettingsRef().rbac_version;
getContext()->checkAccess(required_access); getContext()->checkAccess(required_access);
query.replaceEmptyDatabase(getContext()->getCurrentDatabase()); query.replaceEmptyDatabase(getContext()->getCurrentDatabase());
std::optional<RolesOrUsersSet> roles_from_query; std::optional<RolesOrUsersSet> roles_from_query;
if (query.to_roles) if (query.roles)
roles_from_query = RolesOrUsersSet{*query.to_roles, access_control, getContext()->getUserID()}; roles_from_query = RolesOrUsersSet{*query.roles, access_control, getContext()->getUserID()};
if (query.alter) if (query.alter)
{ {
auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr
{ {
auto updated_policy = typeid_cast<std::shared_ptr<RowPolicy>>(entity->clone()); auto updated_policy = typeid_cast<std::shared_ptr<RowPolicy>>(entity->clone());
updateRowPolicyFromQueryImpl(*updated_policy, query, rbac_version, {}, roles_from_query); updateRowPolicyFromQueryImpl(*updated_policy, query, {}, roles_from_query);
return updated_policy; return updated_policy;
}; };
Strings names = query.names->toStrings(); Strings names = query.names->toStrings();
@ -100,7 +87,7 @@ BlockIO InterpreterCreateRowPolicyQuery::execute()
for (const auto & full_name : query.names->full_names) for (const auto & full_name : query.names->full_names)
{ {
auto new_policy = std::make_shared<RowPolicy>(); auto new_policy = std::make_shared<RowPolicy>();
updateRowPolicyFromQueryImpl(*new_policy, query, rbac_version, full_name, roles_from_query); updateRowPolicyFromQueryImpl(*new_policy, query, full_name, roles_from_query);
new_policies.emplace_back(std::move(new_policy)); new_policies.emplace_back(std::move(new_policy));
} }
@ -116,9 +103,9 @@ BlockIO InterpreterCreateRowPolicyQuery::execute()
} }
void InterpreterCreateRowPolicyQuery::updateRowPolicyFromQuery(RowPolicy & policy, const ASTCreateRowPolicyQuery & query, UInt64 rbac_version) void InterpreterCreateRowPolicyQuery::updateRowPolicyFromQuery(RowPolicy & policy, const ASTCreateRowPolicyQuery & query)
{ {
updateRowPolicyFromQueryImpl(policy, query, rbac_version, {}, {}); updateRowPolicyFromQueryImpl(policy, query, {}, {});
} }

View File

@ -17,7 +17,7 @@ public:
BlockIO execute() override; BlockIO execute() override;
static void updateRowPolicyFromQuery(RowPolicy & policy, const ASTCreateRowPolicyQuery & query, UInt64 rbac_version); static void updateRowPolicyFromQuery(RowPolicy & policy, const ASTCreateRowPolicyQuery & query);
private: private:
AccessRightsElements getRequiredAccess() const; AccessRightsElements getRequiredAccess() const;

View File

@ -129,8 +129,7 @@ BlockIO InterpreterCreateUserQuery::execute()
auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr
{ {
auto updated_user = typeid_cast<std::shared_ptr<User>>(entity->clone()); auto updated_user = typeid_cast<std::shared_ptr<User>>(entity->clone());
updateUserFromQueryImpl(*updated_user, query, {}, default_roles_from_query, settings_from_query, updateUserFromQueryImpl(*updated_user, query, {}, default_roles_from_query, settings_from_query, grantees_from_query, no_password_allowed, plaintext_password_allowed);
grantees_from_query, no_password_allowed, plaintext_password_allowed);
return updated_user; return updated_user;
}; };
@ -149,8 +148,7 @@ BlockIO InterpreterCreateUserQuery::execute()
for (const auto & name : *query.names) for (const auto & name : *query.names)
{ {
auto new_user = std::make_shared<User>(); auto new_user = std::make_shared<User>();
updateUserFromQueryImpl(*new_user, query, name, default_roles_from_query, settings_from_query, updateUserFromQueryImpl(*new_user, query, name, default_roles_from_query, settings_from_query, RolesOrUsersSet::AllTag{}, no_password_allowed, plaintext_password_allowed);
RolesOrUsersSet::AllTag{}, no_password_allowed, plaintext_password_allowed);
new_users.emplace_back(std::move(new_user)); new_users.emplace_back(std::move(new_user));
} }
@ -178,9 +176,9 @@ BlockIO InterpreterCreateUserQuery::execute()
} }
void InterpreterCreateUserQuery::updateUserFromQuery(User & user, const ASTCreateUserQuery & query) void InterpreterCreateUserQuery::updateUserFromQuery(User & user, const ASTCreateUserQuery & query, bool allow_no_password, bool allow_plaintext_password)
{ {
updateUserFromQueryImpl(user, query, {}, {}, {}, {}, true, true); updateUserFromQueryImpl(user, query, {}, {}, {}, {}, allow_no_password, allow_plaintext_password);
} }
} }

View File

@ -17,7 +17,7 @@ public:
BlockIO execute() override; BlockIO execute() override;
static void updateUserFromQuery(User & user, const ASTCreateUserQuery & query); static void updateUserFromQuery(User & user, const ASTCreateUserQuery & query, bool allow_no_password, bool allow_plaintext_password);
private: private:
ASTPtr query_ptr; ASTPtr query_ptr;

View File

@ -70,12 +70,11 @@ ASTs InterpreterShowAccessQuery::getCreateAndGrantQueries() const
{ {
auto entities = getEntities(); auto entities = getEntities();
const auto & access_control = getContext()->getAccessControl(); const auto & access_control = getContext()->getAccessControl();
UInt64 rbac_version = getContext()->getSettingsRef().rbac_version;
ASTs create_queries, grant_queries; ASTs create_queries, grant_queries;
for (const auto & entity : entities) for (const auto & entity : entities)
{ {
create_queries.push_back(InterpreterShowCreateAccessEntityQuery::getCreateQuery(*entity, access_control, rbac_version)); create_queries.push_back(InterpreterShowCreateAccessEntityQuery::getCreateQuery(*entity, access_control));
if (entity->isTypeOf(AccessEntityType::USER) || entity->isTypeOf(AccessEntityType::ROLE)) if (entity->isTypeOf(AccessEntityType::USER) || entity->isTypeOf(AccessEntityType::ROLE))
insertAtEnd(grant_queries, InterpreterShowGrantsQuery::getGrantQueries(*entity, access_control)); insertAtEnd(grant_queries, InterpreterShowGrantsQuery::getGrantQueries(*entity, access_control));
} }

View File

@ -37,8 +37,6 @@ namespace ErrorCodes
extern const int NOT_IMPLEMENTED; extern const int NOT_IMPLEMENTED;
} }
extern const UInt64 RBAC_LATEST_VERSION;
extern const UInt64 RBAC_VERSION_ROW_POLICIES_ARE_SIMPLE_BY_DEFAULT;
namespace namespace
{ {
@ -185,7 +183,6 @@ namespace
ASTPtr getCreateQueryImpl( ASTPtr getCreateQueryImpl(
const RowPolicy & policy, const RowPolicy & policy,
const AccessControl * access_control /* not used if attach_mode == true */, const AccessControl * access_control /* not used if attach_mode == true */,
UInt64 rbac_version,
bool attach_mode) bool attach_mode)
{ {
auto query = std::make_shared<ASTCreateRowPolicyQuery>(); auto query = std::make_shared<ASTCreateRowPolicyQuery>();
@ -193,6 +190,9 @@ namespace
query->names->full_names.emplace_back(policy.getFullName()); query->names->full_names.emplace_back(policy.getFullName());
query->attach = attach_mode; query->attach = attach_mode;
if (policy.isRestrictive())
query->is_restrictive = policy.isRestrictive();
for (auto type : collections::range(RowPolicyFilterType::MAX)) for (auto type : collections::range(RowPolicyFilterType::MAX))
{ {
const auto & filter = policy.filters[static_cast<size_t>(type)]; const auto & filter = policy.filters[static_cast<size_t>(type)];
@ -204,15 +204,12 @@ namespace
} }
} }
if (attach_mode || (rbac_version < RBAC_VERSION_ROW_POLICIES_ARE_SIMPLE_BY_DEFAULT) || (policy.getKind() != RowPolicyKind::SIMPLE))
query->kind = policy.getKind();
if (!policy.to_roles.empty()) if (!policy.to_roles.empty())
{ {
if (attach_mode) if (attach_mode)
query->to_roles = policy.to_roles.toAST(); query->roles = policy.to_roles.toAST();
else else
query->to_roles = policy.to_roles.toASTWithNames(*access_control); query->roles = policy.to_roles.toASTWithNames(*access_control);
} }
return query; return query;
@ -221,7 +218,6 @@ namespace
ASTPtr getCreateQueryImpl( ASTPtr getCreateQueryImpl(
const IAccessEntity & entity, const IAccessEntity & entity,
const AccessControl * access_control /* not used if attach_mode == true */, const AccessControl * access_control /* not used if attach_mode == true */,
UInt64 rbac_version,
bool attach_mode) bool attach_mode)
{ {
if (const User * user = typeid_cast<const User *>(&entity)) if (const User * user = typeid_cast<const User *>(&entity))
@ -229,7 +225,7 @@ namespace
if (const Role * role = typeid_cast<const Role *>(&entity)) if (const Role * role = typeid_cast<const Role *>(&entity))
return getCreateQueryImpl(*role, access_control, attach_mode); return getCreateQueryImpl(*role, access_control, attach_mode);
if (const RowPolicy * policy = typeid_cast<const RowPolicy *>(&entity)) if (const RowPolicy * policy = typeid_cast<const RowPolicy *>(&entity))
return getCreateQueryImpl(*policy, access_control, rbac_version, attach_mode); return getCreateQueryImpl(*policy, access_control, attach_mode);
if (const Quota * quota = typeid_cast<const Quota *>(&entity)) if (const Quota * quota = typeid_cast<const Quota *>(&entity))
return getCreateQueryImpl(*quota, access_control, attach_mode); return getCreateQueryImpl(*quota, access_control, attach_mode);
if (const SettingsProfile * profile = typeid_cast<const SettingsProfile *>(&entity)) if (const SettingsProfile * profile = typeid_cast<const SettingsProfile *>(&entity))
@ -356,23 +352,22 @@ ASTs InterpreterShowCreateAccessEntityQuery::getCreateQueries() const
ASTs list; ASTs list;
const auto & access_control = getContext()->getAccessControl(); const auto & access_control = getContext()->getAccessControl();
UInt64 rbac_version = getContext()->getSettingsRef().rbac_version;
for (const auto & entity : entities) for (const auto & entity : entities)
list.push_back(getCreateQuery(*entity, access_control, rbac_version)); list.push_back(getCreateQuery(*entity, access_control));
return list; return list;
} }
ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const IAccessEntity & entity, const AccessControl & access_control, UInt64 rbac_version) ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const IAccessEntity & entity, const AccessControl & access_control)
{ {
return getCreateQueryImpl(entity, &access_control, rbac_version, false); return getCreateQueryImpl(entity, &access_control, false);
} }
ASTPtr InterpreterShowCreateAccessEntityQuery::getAttachQuery(const IAccessEntity & entity) ASTPtr InterpreterShowCreateAccessEntityQuery::getAttachQuery(const IAccessEntity & entity)
{ {
return getCreateQueryImpl(entity, nullptr, RBAC_LATEST_VERSION, true); return getCreateQueryImpl(entity, nullptr, true);
} }

View File

@ -26,7 +26,7 @@ public:
bool ignoreQuota() const override { return true; } bool ignoreQuota() const override { return true; }
bool ignoreLimits() const override { return true; } bool ignoreLimits() const override { return true; }
static ASTPtr getCreateQuery(const IAccessEntity & entity, const AccessControl & access_control, UInt64 rbac_version); static ASTPtr getCreateQuery(const IAccessEntity & entity, const AccessControl & access_control);
static ASTPtr getAttachQuery(const IAccessEntity & entity); static ASTPtr getAttachQuery(const IAccessEntity & entity);
private: private:

View File

@ -20,10 +20,10 @@ namespace
} }
void formatAsKind(RowPolicyKind kind, const IAST::FormatSettings & settings) void formatAsRestrictiveOrPermissive(bool is_restrictive, const IAST::FormatSettings & settings)
{ {
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " AS " << (settings.hilite ? IAST::hilite_none : "") settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " AS " << (settings.hilite ? IAST::hilite_none : "")
<< RowPolicyKindInfo::get(kind).name; << (is_restrictive ? "restrictive" : "permissive");
} }
@ -156,20 +156,20 @@ void ASTCreateRowPolicyQuery::formatImpl(const FormatSettings & settings, Format
if (!new_short_name.empty()) if (!new_short_name.empty())
formatRenameTo(new_short_name, settings); formatRenameTo(new_short_name, settings);
if (is_restrictive)
formatAsRestrictiveOrPermissive(*is_restrictive, settings);
formatForClauses(filters, alter, settings); formatForClauses(filters, alter, settings);
if (kind) if (roles && (!roles->empty() || alter))
formatAsKind(*kind, settings); formatToRoles(*roles, settings);
if (to_roles)
formatToRoles(*to_roles, settings);
} }
void ASTCreateRowPolicyQuery::replaceCurrentUserTag(const String & current_user_name) const void ASTCreateRowPolicyQuery::replaceCurrentUserTag(const String & current_user_name) const
{ {
if (to_roles) if (roles)
to_roles->replaceCurrentUserTag(current_user_name); roles->replaceCurrentUserTag(current_user_name);
} }
void ASTCreateRowPolicyQuery::replaceEmptyDatabase(const String & current_database) const void ASTCreateRowPolicyQuery::replaceEmptyDatabase(const String & current_database) const

View File

@ -39,10 +39,10 @@ public:
std::shared_ptr<ASTRowPolicyNames> names; std::shared_ptr<ASTRowPolicyNames> names;
String new_short_name; String new_short_name;
std::optional<bool> is_restrictive;
std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters; /// `nullptr` means set to NONE. std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters; /// `nullptr` means set to NONE.
std::optional<RowPolicyKind> kind; std::shared_ptr<ASTRolesOrUsersSet> roles;
std::shared_ptr<ASTRolesOrUsersSet> to_roles;
String getID(char) const override; String getID(char) const override;
ASTPtr clone() const override; ASTPtr clone() const override;

View File

@ -29,24 +29,24 @@ namespace
}); });
} }
bool parseAsKind(IParserBase::Pos & pos, Expected & expected, RowPolicyKind & kind) bool parseAsRestrictiveOrPermissive(IParserBase::Pos & pos, Expected & expected, bool & is_restrictive)
{ {
return IParserBase::wrapParseImpl(pos, [&] return IParserBase::wrapParseImpl(pos, [&]
{ {
if (!ParserKeyword{"AS"}.ignore(pos, expected)) if (!ParserKeyword{"AS"}.ignore(pos, expected))
return false; return false;
for (auto current_kind : collections::range(RowPolicyKind::MAX)) if (ParserKeyword{"RESTRICTIVE"}.ignore(pos, expected))
{ {
const std::string_view & kind_name = RowPolicyKindInfo::get(current_kind).name; is_restrictive = true;
if (ParserKeyword{kind_name.data()}.ignore(pos, expected)) return true;
{
kind = current_kind;
return true;
}
} }
return false; if (!ParserKeyword{"PERMISSIVE"}.ignore(pos, expected))
return false;
is_restrictive = false;
return true;
}); });
} }
@ -243,7 +243,7 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
String cluster = std::exchange(names->cluster, ""); String cluster = std::exchange(names->cluster, "");
String new_short_name; String new_short_name;
std::optional<RowPolicyKind> kind; std::optional<bool> is_restrictive;
std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters; std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters;
while (true) while (true)
@ -251,12 +251,12 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
if (alter && (names->full_names.size() == 1) && new_short_name.empty() && parseRenameTo(pos, expected, new_short_name)) if (alter && (names->full_names.size() == 1) && new_short_name.empty() && parseRenameTo(pos, expected, new_short_name))
continue; continue;
if (!kind) if (!is_restrictive)
{ {
RowPolicyKind new_kind; bool new_is_restrictive;
if (parseAsKind(pos, expected, new_kind)) if (parseAsRestrictiveOrPermissive(pos, expected, new_is_restrictive))
{ {
kind = new_kind; is_restrictive = new_is_restrictive;
continue; continue;
} }
} }
@ -274,8 +274,8 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
break; break;
} }
std::shared_ptr<ASTRolesOrUsersSet> to_roles; std::shared_ptr<ASTRolesOrUsersSet> roles;
parseToRoles(pos, expected, attach_mode, to_roles); parseToRoles(pos, expected, attach_mode, roles);
if (cluster.empty()) if (cluster.empty())
parseOnCluster(pos, expected, cluster); parseOnCluster(pos, expected, cluster);
@ -291,9 +291,9 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
query->cluster = std::move(cluster); query->cluster = std::move(cluster);
query->names = std::move(names); query->names = std::move(names);
query->new_short_name = std::move(new_short_name); query->new_short_name = std::move(new_short_name);
query->kind = kind; query->is_restrictive = is_restrictive;
query->filters = std::move(filters); query->filters = std::move(filters);
query->to_roles = std::move(to_roles); query->roles = std::move(roles);
return true; return true;
} }

View File

@ -10,7 +10,6 @@
#include <DataTypes/DataTypesNumber.h> #include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeUUID.h> #include <DataTypes/DataTypeUUID.h>
#include <DataTypes/DataTypeNullable.h> #include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeEnum.h>
#include <DataTypes/DataTypeArray.h> #include <DataTypes/DataTypeArray.h>
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <Parsers/Access/ASTRolesOrUsersSet.h> #include <Parsers/Access/ASTRolesOrUsersSet.h>
@ -20,26 +19,6 @@
namespace DB namespace DB
{ {
namespace
{
const std::vector<std::pair<String, Int8>> & getRowPolicyKindEnumValues()
{
static const std::vector<std::pair<String, Int8>> values = []
{
std::vector<std::pair<String, Int8>> res;
for (auto kind : collections::range(RowPolicyKind::MAX))
{
const std::string_view & kind_name = RowPolicyKindInfo::get(kind).name;
res.emplace_back(kind_name, static_cast<Int8>(kind));
}
return res;
}();
return values;
}
}
NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes() NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes()
{ {
NamesAndTypesList names_and_types{ NamesAndTypesList names_and_types{
@ -58,7 +37,7 @@ NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes()
} }
NamesAndTypesList extra_names_and_types{ NamesAndTypesList extra_names_and_types{
{"kind", std::make_shared<DataTypeEnum8>(getRowPolicyKindEnumValues())}, {"is_restrictive", std::make_shared<DataTypeUInt8>()},
{"apply_to_all", std::make_shared<DataTypeUInt8>()}, {"apply_to_all", std::make_shared<DataTypeUInt8>()},
{"apply_to_list", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}, {"apply_to_list", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())},
{"apply_to_except", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())} {"apply_to_except", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}
@ -93,7 +72,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
column_filter_null_map[filter_type_i] = &assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData(); column_filter_null_map[filter_type_i] = &assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();
} }
auto & column_kind = assert_cast<ColumnInt8 &>(*res_columns[column_index++]).getData(); auto & column_is_restrictive = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();
auto & column_apply_to_all = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData(); auto & column_apply_to_all = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();
auto & column_apply_to_list = assert_cast<ColumnString &>(assert_cast<ColumnArray &>(*res_columns[column_index]).getData()); auto & column_apply_to_list = assert_cast<ColumnString &>(assert_cast<ColumnArray &>(*res_columns[column_index]).getData());
auto & column_apply_to_list_offsets = assert_cast<ColumnArray &>(*res_columns[column_index++]).getOffsets(); auto & column_apply_to_list_offsets = assert_cast<ColumnArray &>(*res_columns[column_index++]).getOffsets();
@ -105,7 +84,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
const UUID & id, const UUID & id,
const String & storage_name, const String & storage_name,
const std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> & filters, const std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> & filters,
RowPolicyKind kind, bool is_restrictive,
const RolesOrUsersSet & apply_to) const RolesOrUsersSet & apply_to)
{ {
column_name.insertData(name.data(), name.length()); column_name.insertData(name.data(), name.length());
@ -131,7 +110,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
} }
} }
column_kind.push_back(static_cast<Int8>(kind)); column_is_restrictive.push_back(is_restrictive);
auto apply_to_ast = apply_to.toASTWithNames(access_control); auto apply_to_ast = apply_to.toASTWithNames(access_control);
column_apply_to_all.push_back(apply_to_ast->all); column_apply_to_all.push_back(apply_to_ast->all);
@ -154,7 +133,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
if (!storage) if (!storage)
continue; continue;
add_row(policy->getName(), policy->getFullName(), id, storage->getStorageName(), policy->filters, policy->getKind(), policy->to_roles); add_row(policy->getName(), policy->getFullName(), id, storage->getStorageName(), policy->filters, policy->isRestrictive(), policy->to_roles);
} }
} }
} }

View File

@ -2287,16 +2287,6 @@ class ClickHouseInstance:
def copy_file_to_container(self, local_path, dest_path): def copy_file_to_container(self, local_path, dest_path):
return self.cluster.copy_file_to_container(self.docker_id, local_path, dest_path) return self.cluster.copy_file_to_container(self.docker_id, local_path, dest_path)
def copy_dir_to_container(self, local_path, dest_path):
for file_name in os.listdir(local_path):
self.copy_file_to_container(os.path.join(local_path, file_name), os.path.join(dest_path, file_name))
def clear_dir_in_container(self, path):
return self.exec_in_container(['bash', '-c', f'rm -rf {os.path.join(path, "*")}'])
def read_file(node, path):
return node.exec_in_container(['bash', '-c', f'cat {path}'])
def get_process_pid(self, process_name): def get_process_pid(self, process_name):
output = self.exec_in_container(["bash", "-c", output = self.exec_in_container(["bash", "-c",
"ps ax | grep '{}' | grep -v 'grep' | grep -v 'coproc' | grep -v 'bash -c' | awk '{{print $1}}'".format( "ps ax | grep '{}' | grep -v 'grep' | grep -v 'coproc' | grep -v 'bash -c' | awk '{{print $1}}'".format(

View File

@ -42,7 +42,7 @@ def test_create():
assert instance.query( assert instance.query(
"SHOW CREATE USER u2") == "CREATE USER u2 IDENTIFIED WITH sha256_password HOST LOCAL DEFAULT ROLE rx\n" "SHOW CREATE USER u2") == "CREATE USER u2 IDENTIFIED WITH sha256_password HOST LOCAL DEFAULT ROLE rx\n"
assert instance.query( assert instance.query(
"SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 AS permissive TO u1, u2\n" "SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 TO u1, u2\n"
assert instance.query( assert instance.query(
"SHOW CREATE QUOTA q") == "CREATE QUOTA q FOR INTERVAL 1 hour MAX queries = 100 TO ALL EXCEPT rx\n" "SHOW CREATE QUOTA q") == "CREATE QUOTA q FOR INTERVAL 1 hour MAX queries = 100 TO ALL EXCEPT rx\n"
assert instance.query("SHOW GRANTS FOR u1") == "" assert instance.query("SHOW GRANTS FOR u1") == ""

View File

@ -1,48 +0,0 @@
import pytest
from helpers.cluster import ClickHouseCluster
from helpers.test_tools import TSV
import os.path
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
cluster = ClickHouseCluster(__file__)
node = cluster.add_instance('instance', stay_alive=True)
@pytest.fixture(scope="module", autouse=True)
def started_cluster():
try:
cluster.start()
yield cluster
finally:
cluster.shutdown()
def test_version_1():
node.stop_clickhouse()
node.clear_dir_in_container("/var/lib/clickhouse/access")
node.copy_dir_to_container(os.path.join(SCRIPT_DIR, "version_1"), "/var/lib/clickhouse/access")
node.start_clickhouse()
assert node.query("SELECT name, select_filter, kind FROM system.row_policies ORDER BY name") == TSV([['p0 ON mydb.mytable', 'a = 0', 'permissive'],
['p1 ON mydb.mytable', 'a = 1000', 'permissive'],
['p2 ON mydb.mytable', 'a = 2000', 'restrictive'],
['p3 ON mydb.mytable', 'a = 3000', 'simple']])
u0_id = node.query("SELECT id FROM system.users WHERE name='u0'").rstrip()
p0_id = node.query("SELECT id FROM system.row_policies WHERE name='p0 ON mydb.mytable'").rstrip()
assert node.read_file(os.path.join("/var/lib/clickhouse/access", p0_id + ".sql")) == \
f"ATTACH ROW POLICY p0 ON mydb.mytable FOR SELECT USING a = 0 TO ID('{u0_id}');\n"
node.query("ALTER ROW POLICY p0 ON mydb.mytable FOR SELECT USING a=1")
assert node.read_file(os.path.join("/var/lib/clickhouse/access", p0_id + ".sql")) == \
f"SET rbac_version = 2;\n"\
f"ATTACH ROW POLICY p0 ON mydb.mytable FOR SELECT USING a = 1 AS permissive TO ID('{u0_id}');\n"
node.query("CREATE ROW POLICY p4 ON mydb.mytable FOR SELECT USING a=4000")
p4_id = node.query("SELECT id FROM system.row_policies WHERE name='p4 ON mydb.mytable'").rstrip()
assert node.read_file(os.path.join("/var/lib/clickhouse/access", p4_id + ".sql")) == \
f"SET rbac_version = 2;\n"\
f"ATTACH ROW POLICY p4 ON mydb.mytable FOR SELECT USING a = 4000 AS permissive;\n"

View File

@ -1 +0,0 @@
ATTACH ROW POLICY p0 ON mydb.mytable FOR SELECT USING a = 0 TO ID('a44bf717-218f-09e8-e1cd-f101f5b7cbbb');

View File

@ -1 +0,0 @@
ATTACH ROW POLICY p1 ON mydb.mytable FOR SELECT USING a = 1000 AS permissive TO ID('964a717c-05cd-2ba0-d398-6624e778e99a');

View File

@ -1 +0,0 @@
ATTACH ROW POLICY p3 ON mydb.mytable FOR SELECT USING a = 3000 AS simple TO ID('004ba500-8a3d-5746-7d4a-f37172faa69e');

View File

@ -1 +0,0 @@
ATTACH ROW POLICY p2 ON mydb.mytable FOR SELECT USING a = 2000 AS restrictive TO ID('48494a8a-aad1-4cd3-1f17-af53613e85be');

View File

@ -256,21 +256,21 @@ def test_reload_users_xml_by_timer():
def test_introspection(): def test_introspection():
policies = [ policies = [
["another ON mydb.filtered_table1", "another", "mydb", "filtered_table1", ["another ON mydb.filtered_table1", "another", "mydb", "filtered_table1",
"6068883a-0e9d-f802-7e22-0144f8e66d3c", "users.xml", "1", "permissive", 0, "['another']", "[]"], "6068883a-0e9d-f802-7e22-0144f8e66d3c", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.filtered_table2", "another", "mydb", "filtered_table2", ["another ON mydb.filtered_table2", "another", "mydb", "filtered_table2",
"c019e957-c60b-d54e-cc52-7c90dac5fb01", "users.xml", "1", "permissive", 0, "['another']", "[]"], "c019e957-c60b-d54e-cc52-7c90dac5fb01", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.filtered_table3", "another", "mydb", "filtered_table3", ["another ON mydb.filtered_table3", "another", "mydb", "filtered_table3",
"4cb080d0-44e8-dbef-6026-346655143628", "users.xml", "1", "permissive", 0, "['another']", "[]"], "4cb080d0-44e8-dbef-6026-346655143628", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.local", "another", "mydb", "local", "5b23c389-7e18-06bf-a6bc-dd1afbbc0a97", "users.xml", ["another ON mydb.local", "another", "mydb", "local", "5b23c389-7e18-06bf-a6bc-dd1afbbc0a97", "users.xml",
"a = 1", "permissive", 0, "['another']", "[]"], "a = 1", 0, 0, "['another']", "[]"],
["default ON mydb.filtered_table1", "default", "mydb", "filtered_table1", ["default ON mydb.filtered_table1", "default", "mydb", "filtered_table1",
"9e8a8f62-4965-2b5e-8599-57c7b99b3549", "users.xml", "a = 1", "permissive", 0, "['default']", "[]"], "9e8a8f62-4965-2b5e-8599-57c7b99b3549", "users.xml", "a = 1", 0, 0, "['default']", "[]"],
["default ON mydb.filtered_table2", "default", "mydb", "filtered_table2", ["default ON mydb.filtered_table2", "default", "mydb", "filtered_table2",
"cffae79d-b9bf-a2ef-b798-019c18470b25", "users.xml", "a + b < 1 or c - d > 5", "permissive", 0, "['default']", "[]"], "cffae79d-b9bf-a2ef-b798-019c18470b25", "users.xml", "a + b < 1 or c - d > 5", 0, 0, "['default']", "[]"],
["default ON mydb.filtered_table3", "default", "mydb", "filtered_table3", ["default ON mydb.filtered_table3", "default", "mydb", "filtered_table3",
"12fc5cef-e3da-3940-ec79-d8be3911f42b", "users.xml", "c = 1", "permissive", 0, "['default']", "[]"], "12fc5cef-e3da-3940-ec79-d8be3911f42b", "users.xml", "c = 1", 0, 0, "['default']", "[]"],
["default ON mydb.local", "default", "mydb", "local", "cdacaeb5-1d97-f99d-2bb0-4574f290629c", "users.xml", "1", ["default ON mydb.local", "default", "mydb", "local", "cdacaeb5-1d97-f99d-2bb0-4574f290629c", "users.xml", "1",
"permissive", 0, "['default']", "[]"] 0, 0, "['default']", "[]"]
] ]
assert node.query("SELECT * from system.row_policies ORDER BY short_name, database, table") == TSV(policies) assert node.query("SELECT * from system.row_policies ORDER BY short_name, database, table") == TSV(policies)
@ -292,49 +292,49 @@ def test_dcl_introspection():
"default ON mydb.local"]) "default ON mydb.local"])
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.local") == "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.local") == "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default\n"
assert node.query("SHOW CREATE POLICY default") == TSV( assert node.query("SHOW CREATE POLICY default") == TSV(
["CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default", ["CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"]) "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
assert node.query("SHOW CREATE POLICIES ON mydb.filtered_table1") == TSV( assert node.query("SHOW CREATE POLICIES ON mydb.filtered_table1") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another", ["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default"]) "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default"])
assert node.query("SHOW CREATE POLICIES ON mydb.*") == TSV( assert node.query("SHOW CREATE POLICIES ON mydb.*") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another", ["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"]) "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
assert node.query("SHOW CREATE POLICIES") == TSV( assert node.query("SHOW CREATE POLICIES") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another", ["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another", "CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"]) "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
expected_access = "CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another\n" \ expected_access = "CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another\n" \ "CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another\n" \ "CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another\n" \ "CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another\n" \
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default\n" \ "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default\n" \ "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default\n" \ "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default\n" \
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default\n" "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default\n"
assert expected_access in node.query("SHOW ACCESS") assert expected_access in node.query("SHOW ACCESS")
copy_policy_xml('all_rows.xml') copy_policy_xml('all_rows.xml')
@ -342,22 +342,22 @@ def test_dcl_introspection():
["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3", ["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3",
"default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"]) "default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"])
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING 1 TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING 1 TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING 1 TO default\n"
copy_policy_xml('no_rows.xml') copy_policy_xml('no_rows.xml')
assert node.query("SHOW POLICIES") == TSV( assert node.query("SHOW POLICIES") == TSV(
["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3", ["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3",
"default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"]) "default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"])
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING NULL AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING NULL TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING NULL AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING NULL TO default\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING NULL AS permissive TO default\n" "SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING NULL TO default\n"
copy_policy_xml('no_filters.xml') copy_policy_xml('no_filters.xml')
assert node.query("SHOW POLICIES") == "" assert node.query("SHOW POLICIES") == ""
@ -382,7 +382,7 @@ def test_dcl_management():
assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[1, 0]]) assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[1, 0]])
assert node.query("SHOW POLICIES ON mydb.filtered_table1") == "pB\n" assert node.query("SHOW POLICIES ON mydb.filtered_table1") == "pB\n"
assert node.query( assert node.query(
"SHOW CREATE POLICY pB ON mydb.filtered_table1") == "CREATE ROW POLICY pB ON mydb.filtered_table1 FOR SELECT USING a > b AS permissive TO default\n" "SHOW CREATE POLICY pB ON mydb.filtered_table1") == "CREATE ROW POLICY pB ON mydb.filtered_table1 FOR SELECT USING a > b TO default\n"
node.query("DROP POLICY pB ON mydb.filtered_table1") node.query("DROP POLICY pB ON mydb.filtered_table1")
assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]]) assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]])
@ -439,34 +439,6 @@ def test_users_xml_is_readonly():
assert re.search("storage is readonly", node.query_and_get_error("DROP POLICY default ON mydb.filtered_table1")) assert re.search("storage is readonly", node.query_and_get_error("DROP POLICY default ON mydb.filtered_table1"))
def test_some_users_without_policies():
copy_policy_xml('no_filters.xml')
assert node.query("SHOW POLICIES") == ""
node.query("CREATE USER X, Y")
node.query("GRANT SELECT ON mydb.filtered_table1 TO X, Y")
node.query("CREATE POLICY pA ON mydb.filtered_table1 FOR SELECT USING a < b AS permissive TO X")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == ""
node.query("ALTER POLICY pA ON mydb.filtered_table1 AS restrictive")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == ""
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == ""
node.query("CREATE POLICY pB ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO X")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == ""
node.query("ALTER POLICY pB ON mydb.filtered_table1 TO X, Y")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == TSV([[0, 0], [0, 1], [1, 0], [1, 1]])
node.query("DROP POLICY pB ON mydb.filtered_table1")
node.query("ALTER POLICY pA ON mydb.filtered_table1 AS simple")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == TSV([[0, 0], [0, 1], [1, 0], [1, 1]])
node.query("DROP USER X, Y")
def test_tags_with_db_and_table_names(): def test_tags_with_db_and_table_names():
copy_policy_xml('tags_with_db_and_table_names.xml') copy_policy_xml('tags_with_db_and_table_names.xml')
@ -476,10 +448,10 @@ def test_tags_with_db_and_table_names():
assert node.query("SELECT * FROM mydb.`.filtered_table4`") == TSV([[1, 1]]) assert node.query("SELECT * FROM mydb.`.filtered_table4`") == TSV([[1, 1]])
assert node.query("SHOW CREATE POLICIES default") == TSV( assert node.query("SHOW CREATE POLICIES default") == TSV(
["CREATE ROW POLICY default ON mydb.`.filtered_table4` FOR SELECT USING c = 2 AS permissive TO default", ["CREATE ROW POLICY default ON mydb.`.filtered_table4` FOR SELECT USING c = 2 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING c > (d + 5) AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING c > (d + 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 0 AS permissive TO default", "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 0 TO default",
"CREATE ROW POLICY default ON mydb.table FOR SELECT USING a = 0 AS permissive TO default"]) "CREATE ROW POLICY default ON mydb.table FOR SELECT USING a = 0 TO default"])
def test_miscellaneous_engines(): def test_miscellaneous_engines():

View File

@ -1,35 +1,35 @@
-- default -- default
CREATE ROW POLICY p1_01295 ON db.table AS permissive CREATE ROW POLICY p1_01295 ON db.table
-- same as default -- same as default
CREATE ROW POLICY p2_01295 ON db.table AS permissive CREATE ROW POLICY p2_01295 ON db.table
CREATE ROW POLICY p3_01295 ON db.table AS permissive CREATE ROW POLICY p3_01295 ON db.table
-- rename -- rename
CREATE ROW POLICY p2_01295_renamed ON db.table AS permissive CREATE ROW POLICY p2_01295_renamed ON db.table
-- filter -- filter
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING (a < b) AND (c > d) AS permissive CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING (a < b) AND (c > d)
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING id = currentUser() AS restrictive CREATE ROW POLICY p2_01295 ON db.table AS restrictive FOR SELECT USING id = currentUser()
CREATE ROW POLICY p3_01295 ON db.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p3_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 0 AS restrictive CREATE ROW POLICY p1_01295 ON db.table AS restrictive FOR SELECT USING 0
-- to roles -- to roles
CREATE ROW POLICY p1_01295 ON db.table AS permissive CREATE ROW POLICY p1_01295 ON db.table
CREATE ROW POLICY p2_01295 ON db.table AS permissive TO ALL CREATE ROW POLICY p2_01295 ON db.table TO ALL
CREATE ROW POLICY p3_01295 ON db.table AS permissive TO r1_01295 CREATE ROW POLICY p3_01295 ON db.table TO r1_01295
CREATE ROW POLICY p4_01295 ON db.table AS permissive TO u1_01295 CREATE ROW POLICY p4_01295 ON db.table TO u1_01295
CREATE ROW POLICY p5_01295 ON db.table AS permissive TO r1_01295, u1_01295 CREATE ROW POLICY p5_01295 ON db.table TO r1_01295, u1_01295
CREATE ROW POLICY p6_01295 ON db.table AS permissive TO ALL EXCEPT r1_01295 CREATE ROW POLICY p6_01295 ON db.table TO ALL EXCEPT r1_01295
CREATE ROW POLICY p7_01295 ON db.table AS permissive TO ALL EXCEPT r1_01295, u1_01295 CREATE ROW POLICY p7_01295 ON db.table TO ALL EXCEPT r1_01295, u1_01295
CREATE ROW POLICY p1_01295 ON db.table AS permissive TO u1_01295 CREATE ROW POLICY p1_01295 ON db.table TO u1_01295
CREATE ROW POLICY p2_01295 ON db.table AS permissive CREATE ROW POLICY p2_01295 ON db.table
-- multiple policies in one command -- multiple policies in one command
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p3_01295 ON db.table AS permissive TO u1_01295 CREATE ROW POLICY p3_01295 ON db.table TO u1_01295
CREATE ROW POLICY p3_01295 ON db2.table2 AS permissive TO u1_01295 CREATE ROW POLICY p3_01295 ON db2.table2 TO u1_01295
CREATE ROW POLICY p4_01295 ON db.table FOR SELECT USING a = b AS permissive CREATE ROW POLICY p4_01295 ON db.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01295 ON db2.table2 FOR SELECT USING a = b AS permissive CREATE ROW POLICY p5_01295 ON db2.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 AS permissive TO ALL CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 TO ALL
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 AS permissive TO ALL CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 TO ALL
-- system.row_policies -- system.row_policies
p1_01295 ON db.table p1_01295 db table local directory (a < b) AND (c > d) permissive 0 [] [] p1_01295 ON db.table p1_01295 db table local directory (a < b) AND (c > d) 0 0 [] []
p2_01295 ON db.table p2_01295 db table local directory id = currentUser() restrictive 0 ['u1_01295'] [] p2_01295 ON db.table p2_01295 db table local directory id = currentUser() 1 0 ['u1_01295'] []
p3_01295 ON db.table p3_01295 db table local directory 1 permissive 1 [] ['r1_01295'] p3_01295 ON db.table p3_01295 db table local directory 1 0 1 [] ['r1_01295']

View File

@ -72,7 +72,7 @@ SELECT '-- system.row_policies';
CREATE ROW POLICY p1_01295 ON db.table USING a<b AND c>d; CREATE ROW POLICY p1_01295 ON db.table USING a<b AND c>d;
CREATE ROW POLICY p2_01295 ON db.table USING id=currentUser() AS RESTRICTIVE TO u1_01295; CREATE ROW POLICY p2_01295 ON db.table USING id=currentUser() AS RESTRICTIVE TO u1_01295;
CREATE ROW POLICY p3_01295 ON db.table USING 1 AS PERMISSIVE TO ALL EXCEPT r1_01295; CREATE ROW POLICY p3_01295 ON db.table USING 1 AS PERMISSIVE TO ALL EXCEPT r1_01295;
SELECT name, short_name, database, table, storage, select_filter, kind, apply_to_all, apply_to_list, apply_to_except from system.row_policies WHERE short_name LIKE 'p%\_01295' ORDER BY name; SELECT name, short_name, database, table, storage, select_filter, is_restrictive, apply_to_all, apply_to_list, apply_to_except from system.row_policies WHERE short_name LIKE 'p%\_01295' ORDER BY name;
DROP ROW POLICY p1_01295, p2_01295, p3_01295 ON db.table; DROP ROW POLICY p1_01295, p2_01295, p3_01295 ON db.table;
DROP ROLE r1_01295; DROP ROLE r1_01295;

View File

@ -1,20 +1,20 @@
-- one policy -- one policy
CREATE ROW POLICY p1_01296 ON db_01296.table AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table
CREATE ROW POLICY p1_01296 ON db_01296.table AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
-- multiple policies -- multiple policies
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p3_01296 ON db_01296.table AS permissive TO u1_01296 CREATE ROW POLICY p3_01296 ON db_01296.table TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 AS permissive TO u1_01296 CREATE ROW POLICY p3_01296 ON db_01296.table2 TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b AS permissive CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b AS permissive CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p3_01296 ON db_01296.table AS permissive TO u1_01296 CREATE ROW POLICY p3_01296 ON db_01296.table TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 AS permissive TO u1_01296 CREATE ROW POLICY p3_01296 ON db_01296.table2 TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b AS permissive CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b AS permissive CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive TO ALL CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 TO ALL
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive TO ALL CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 TO ALL

View File

@ -49,7 +49,7 @@ CREATE TABLE system.replicated_merge_tree_settings\n(\n `name` String,\n `
CREATE TABLE system.replication_queue\n(\n `database` String,\n `table` String,\n `replica_name` String,\n `position` UInt32,\n `node_name` String,\n `type` String,\n `create_time` DateTime,\n `required_quorum` UInt32,\n `source_replica` String,\n `new_part_name` String,\n `parts_to_merge` Array(String),\n `is_detach` UInt8,\n `is_currently_executing` UInt8,\n `num_tries` UInt32,\n `last_exception` String,\n `last_attempt_time` DateTime,\n `num_postponed` UInt32,\n `postpone_reason` String,\n `last_postpone_time` DateTime,\n `merge_type` String\n)\nENGINE = SystemReplicationQueue()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.replication_queue\n(\n `database` String,\n `table` String,\n `replica_name` String,\n `position` UInt32,\n `node_name` String,\n `type` String,\n `create_time` DateTime,\n `required_quorum` UInt32,\n `source_replica` String,\n `new_part_name` String,\n `parts_to_merge` Array(String),\n `is_detach` UInt8,\n `is_currently_executing` UInt8,\n `num_tries` UInt32,\n `last_exception` String,\n `last_attempt_time` DateTime,\n `num_postponed` UInt32,\n `postpone_reason` String,\n `last_postpone_time` DateTime,\n `merge_type` String\n)\nENGINE = SystemReplicationQueue()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.role_grants\n(\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `granted_role_name` String,\n `granted_role_is_default` UInt8,\n `with_admin_option` UInt8\n)\nENGINE = SystemRoleGrants()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.role_grants\n(\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `granted_role_name` String,\n `granted_role_is_default` UInt8,\n `with_admin_option` UInt8\n)\nENGINE = SystemRoleGrants()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.roles\n(\n `name` String,\n `id` UUID,\n `storage` String\n)\nENGINE = SystemRoles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.roles\n(\n `name` String,\n `id` UUID,\n `storage` String\n)\nENGINE = SystemRoles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.row_policies\n(\n `name` String,\n `short_name` String,\n `database` String,\n `table` String,\n `id` UUID,\n `storage` String,\n `select_filter` Nullable(String),\n `kind` Enum8(\'permissive\' = 0, \'restrictive\' = 1, \'simple\' = 2),\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemRowPolicies()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.row_policies\n(\n `name` String,\n `short_name` String,\n `database` String,\n `table` String,\n `id` UUID,\n `storage` String,\n `select_filter` Nullable(String),\n `is_restrictive` UInt8,\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemRowPolicies()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings\n(\n `name` String,\n `value` String,\n `changed` UInt8,\n `description` String,\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` UInt8,\n `type` String\n)\nENGINE = SystemSettings()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.settings\n(\n `name` String,\n `value` String,\n `changed` UInt8,\n `description` String,\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` UInt8,\n `type` String\n)\nENGINE = SystemSettings()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings_profile_elements\n(\n `profile_name` Nullable(String),\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `index` UInt64,\n `setting_name` Nullable(String),\n `value` Nullable(String),\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` Nullable(UInt8),\n `inherit_profile` Nullable(String)\n)\nENGINE = SystemSettingsProfileElements()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.settings_profile_elements\n(\n `profile_name` Nullable(String),\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `index` UInt64,\n `setting_name` Nullable(String),\n `value` Nullable(String),\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` Nullable(UInt8),\n `inherit_profile` Nullable(String)\n)\nENGINE = SystemSettingsProfileElements()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings_profiles\n(\n `name` String,\n `id` UUID,\n `storage` String,\n `num_elements` UInt64,\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemSettingsProfiles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\' CREATE TABLE system.settings_profiles\n(\n `name` String,\n `id` UUID,\n `storage` String,\n `num_elements` UInt64,\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemSettingsProfiles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'

View File

@ -1,32 +0,0 @@
None
1
2
3
4
R1: x == 1
1
R1, R2: (x == 1) OR (x == 2)
1
2
R1, R2, R3: (x == 1) OR (x == 2) OR (x == 3)
1
2
3
R1, R2, R3, R4: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2)
1
2
R1, R2, R3, R4, R5: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)
2
R2, R3, R4, R5: ((x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)
2
R3, R4, R5: (x == 3) AND (x <= 2) AND (x >= 2)
R4, R5: FALSE(no permissive filters) AND (x <= 2) AND (x >= 2)
R5: (x >= 2)
2
3
4
None
1
2
3
4

View File

@ -1,54 +0,0 @@
DROP TABLE IF EXISTS 02131_multiple_row_policies_on_same_column;
CREATE TABLE 02131_multiple_row_policies_on_same_column (x UInt8) ENGINE = MergeTree ORDER BY x;
INSERT INTO 02131_multiple_row_policies_on_same_column VALUES (1), (2), (3), (4);
DROP ROW POLICY IF EXISTS 02131_filter_1 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_2 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_3 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_4 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_5 ON 02131_multiple_row_policies_on_same_column;
SELECT 'None';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_1 ON 02131_multiple_row_policies_on_same_column USING x=1 AS permissive TO ALL;
SELECT 'R1: x == 1';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_2 ON 02131_multiple_row_policies_on_same_column USING x=2 AS permissive TO ALL;
SELECT 'R1, R2: (x == 1) OR (x == 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_3 ON 02131_multiple_row_policies_on_same_column USING x=3 AS permissive TO ALL;
SELECT 'R1, R2, R3: (x == 1) OR (x == 2) OR (x == 3)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_4 ON 02131_multiple_row_policies_on_same_column USING x<=2 AS restrictive TO ALL;
SELECT 'R1, R2, R3, R4: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_5 ON 02131_multiple_row_policies_on_same_column USING x>=2 AS simple TO ALL;
SELECT 'R1, R2, R3, R4, R5: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_1 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R2, R3, R4, R5: ((x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_2 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R3, R4, R5: (x == 3) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_3 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R4, R5: FALSE(no permissive filters) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_4 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R5: (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_5 ON 02131_multiple_row_policies_on_same_column;
SELECT 'None';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP TABLE 02131_multiple_row_policies_on_same_column;

View File

@ -0,0 +1,8 @@
4
1
2
3
3
3
3
4

View File

@ -0,0 +1,32 @@
SET optimize_move_to_prewhere = 1;
DROP TABLE IF EXISTS 02131_multiply_row_policies_on_same_column;
CREATE TABLE 02131_multiply_row_policies_on_same_column (x UInt8) ENGINE = MergeTree ORDER BY x;
INSERT INTO 02131_multiply_row_policies_on_same_column VALUES (1), (2), (3), (4);
DROP ROW POLICY IF EXISTS 02131_filter_1 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_2 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_3 ON 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_1 ON 02131_multiply_row_policies_on_same_column USING x=1 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_2 ON 02131_multiply_row_policies_on_same_column USING x=2 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_3 ON 02131_multiply_row_policies_on_same_column USING x=3 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_4 ON 02131_multiply_row_policies_on_same_column USING x<4 AS RESTRICTIVE TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_1 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_2 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_3 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_4 ON 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
DROP TABLE 02131_multiply_row_policies_on_same_column;

View File

@ -1,18 +0,0 @@
rbac_version=1
CREATE ROW POLICY `02240_r1` ON db1.table1 AS permissive
CREATE ROW POLICY `02240_r2` ON db1.table1 AS permissive
CREATE ROW POLICY `02240_r3` ON db1.table1 AS restrictive
CREATE ROW POLICY `02240_r4` ON db1.table1 AS simple
02240_r1 permissive
02240_r2 permissive
02240_r3 restrictive
02240_r4 simple
rbac_version=2
CREATE ROW POLICY `02240_r1` ON db1.table1
CREATE ROW POLICY `02240_r2` ON db1.table1 AS permissive
CREATE ROW POLICY `02240_r3` ON db1.table1 AS restrictive
CREATE ROW POLICY `02240_r4` ON db1.table1
02240_r1 simple
02240_r2 permissive
02240_r3 restrictive
02240_r4 simple

View File

@ -1,22 +0,0 @@
DROP ROW POLICY IF EXISTS 02240_r1, 02240_r2, 02240_r3, 02240_r4 ON db1.table1;
SELECT concat('rbac_version=', toString(getSetting('rbac_version')));
CREATE ROW POLICY 02240_r1 ON db1.table1;
CREATE ROW POLICY 02240_r2 ON db1.table1 AS permissive;
CREATE ROW POLICY 02240_r3 ON db1.table1 AS restrictive;
CREATE ROW POLICY 02240_r4 ON db1.table1 AS simple;
SHOW CREATE ROW POLICY 02240_r1, 02240_r2, 02240_r3, 02240_r4 ON db1.table1;
SELECT short_name, kind FROM system.row_policies WHERE short_name LIKE '02240%' ORDER BY short_name;
DROP ROW POLICY 02240_r1, 02240_r2, 02240_r3, 02240_r4 ON db1.table1;
SET rbac_version=2;
SELECT concat('rbac_version=', toString(getSetting('rbac_version')));
CREATE ROW POLICY 02240_r1 ON db1.table1;
CREATE ROW POLICY 02240_r2 ON db1.table1 AS permissive;
CREATE ROW POLICY 02240_r3 ON db1.table1 AS restrictive;
CREATE ROW POLICY 02240_r4 ON db1.table1 AS simple;
SHOW CREATE ROW POLICY 02240_r1, 02240_r2, 02240_r3, 02240_r4 ON db1.table1;
SELECT short_name, kind FROM system.row_policies WHERE short_name LIKE '02240%' ORDER BY short_name;
DROP ROW POLICY 02240_r1, 02240_r2, 02240_r3, 02240_r4 ON db1.table1;
SET rbac_version=1;