Fix permission for newer queries (#156)

This commit is contained in:
antonio2368 2021-05-26 10:02:25 +02:00 committed by GitHub
parent 8a99670301
commit 13ea35af2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 47 deletions

View File

@ -9,6 +9,8 @@
* Fixed memory tracking issues. Some of the allocation and deallocation weren't
tracked during the query execution.
* Fixed reading CSV files that are using CRLF as the newline symbol.
* Fixed permission issues for `LOAD CSV`, `FREE MEMORY`, `LOCK DATA DIRECTORY`,
and replication queries.
## v1.4.0

View File

@ -2232,6 +2232,7 @@ const std::vector<AuthQuery::Privilege> kPrivilegesAll = {
AuthQuery::Privilege::AUTH,
AuthQuery::Privilege::CONSTRAINT, AuthQuery::Privilege::DUMP,
AuthQuery::Privilege::REPLICATION,
AuthQuery::Privilege::READ_FILE,
AuthQuery::Privilege::LOCK_PATH,
AuthQuery::Privilege::FREE_MEMORY};
cpp<#

View File

@ -109,6 +109,6 @@ class ExpressionVisitor
template <class TResult>
class QueryVisitor
: public ::utils::Visitor<TResult, CypherQuery, ExplainQuery, ProfileQuery, IndexQuery, AuthQuery, InfoQuery,
ConstraintQuery, DumpQuery, ReplicationQuery, LockPathQuery, LoadCsv, FreeMemoryQuery> {};
ConstraintQuery, DumpQuery, ReplicationQuery, LockPathQuery, FreeMemoryQuery> {};
} // namespace query

View File

@ -767,6 +767,10 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext
if (ctx->AUTH()) return AuthQuery::Privilege::AUTH;
if (ctx->CONSTRAINT()) return AuthQuery::Privilege::CONSTRAINT;
if (ctx->DUMP()) return AuthQuery::Privilege::DUMP;
if (ctx->REPLICATION()) return AuthQuery::Privilege::REPLICATION;
if (ctx->LOCK_PATH()) return AuthQuery::Privilege::LOCK_PATH;
if (ctx->READ_FILE()) return AuthQuery::Privilege::READ_FILE;
if (ctx->FREE_MEMORY()) return AuthQuery::Privilege::FREE_MEMORY;
LOG_FATAL("Should not get here - unknown privilege!");
}

View File

@ -117,7 +117,7 @@ delimiter : literal ;
quote : literal ;
rowVar : variable ;
rowVar : variable ;
userOrRoleName : symbolicName ;
@ -146,8 +146,22 @@ denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole
revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ;
privilege : CREATE | DELETE | MATCH | MERGE | SET
| REMOVE | INDEX | STATS | AUTH | CONSTRAINT | DUMP ;
privilege : CREATE
| DELETE
| MATCH
| MERGE
| SET
| REMOVE
| INDEX
| STATS
| AUTH
| CONSTRAINT
| DUMP
| REPLICATION
| LOCK_PATH
| READ_FILE
| FREE_MEMORY
;
privilegeList : privilege ( ',' privilege )* ;

View File

@ -10,6 +10,8 @@ lexer grammar MemgraphCypherLexer ;
import CypherLexer ;
UNDERSCORE : '_' ;
ALTER : A L T E R ;
ASYNC : A S Y N C ;
AUTH : A U T H ;
@ -25,6 +27,7 @@ DROP : D R O P ;
DUMP : D U M P ;
FOR : F O R ;
FREE : F R E E ;
FREE_MEMORY : F R E E UNDERSCORE M E M O R Y ;
FROM : F R O M ;
GRANT : G R A N T ;
GRANTS : G R A N T S ;
@ -33,12 +36,14 @@ IDENTIFIED : I D E N T I F I E D ;
IGNORE : I G N O R E ;
LOAD : L O A D ;
LOCK : L O C K ;
LOCK_PATH : L O C K UNDERSCORE P A T H ;
MAIN : M A I N ;
MODE : M O D E ;
NO : N O ;
PASSWORD : P A S S W O R D ;
PORT : P O R T ;
PRIVILEGES : P R I V I L E G E S ;
READ_FILE : R E A D UNDERSCORE F I L E ;
REGISTER : R E G I S T E R ;
REPLICA : R E P L I C A ;
REPLICAS : R E P L I C A S ;

View File

@ -51,74 +51,58 @@ class PrivilegeExtractor : public QueryVisitor<void>, public HierarchicalTreeVis
void Visit(LockPathQuery &lock_path_query) override { AddPrivilege(AuthQuery::Privilege::LOCK_PATH); }
void Visit(LoadCsv &load_csv) override { AddPrivilege(AuthQuery::Privilege::READ_FILE); }
void Visit(FreeMemoryQuery &free_memory_query) override { AddPrivilege(AuthQuery::Privilege::FREE_MEMORY); }
void Visit(ReplicationQuery &replication_query) override {
switch (replication_query.action_) {
case ReplicationQuery::Action::SET_REPLICATION_ROLE:
AddPrivilege(AuthQuery::Privilege::REPLICATION);
break;
case ReplicationQuery::Action::SHOW_REPLICATION_ROLE:
AddPrivilege(AuthQuery::Privilege::REPLICATION);
break;
case ReplicationQuery::Action::REGISTER_REPLICA:
AddPrivilege(AuthQuery::Privilege::REPLICATION);
break;
case ReplicationQuery::Action::DROP_REPLICA:
AddPrivilege(AuthQuery::Privilege::REPLICATION);
break;
case ReplicationQuery::Action::SHOW_REPLICAS:
AddPrivilege(AuthQuery::Privilege::REPLICATION);
break;
}
}
void Visit(ReplicationQuery &replication_query) override { AddPrivilege(AuthQuery::Privilege::REPLICATION); }
bool PreVisit(Create &) override {
bool PreVisit(Create & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::CREATE);
return false;
}
bool PreVisit(CallProcedure &) override {
bool PreVisit(CallProcedure & /*unused*/) override {
// TODO: Corresponding privilege
return false;
}
bool PreVisit(Delete &) override {
bool PreVisit(Delete & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::DELETE);
return false;
}
bool PreVisit(Match &) override {
bool PreVisit(Match & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::MATCH);
return false;
}
bool PreVisit(Merge &) override {
bool PreVisit(Merge & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::MERGE);
return false;
}
bool PreVisit(SetProperty &) override {
bool PreVisit(SetProperty & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::SET);
return false;
}
bool PreVisit(SetProperties &) override {
bool PreVisit(SetProperties & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::SET);
return false;
}
bool PreVisit(SetLabels &) override {
bool PreVisit(SetLabels & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::SET);
return false;
}
bool PreVisit(RemoveProperty &) override {
bool PreVisit(RemoveProperty & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::REMOVE);
return false;
}
bool PreVisit(RemoveLabels &) override {
bool PreVisit(RemoveLabels & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::REMOVE);
return false;
}
bool PreVisit(LoadCsv & /*unused*/) override {
AddPrivilege(AuthQuery::Privilege::READ_FILE);
return false;
}
bool Visit(Identifier &) override { return true; }
bool Visit(PrimitiveLiteral &) override { return true; }
bool Visit(ParameterLookup &) override { return true; }
bool Visit(Identifier & /*unused*/) override { return true; }
bool Visit(PrimitiveLiteral & /*unused*/) override { return true; }
bool Visit(ParameterLookup & /*unused*/) override { return true; }
private:
void AddPrivilege(AuthQuery::Privilege privilege) {

View File

@ -79,15 +79,15 @@ class Trie {
const int kBitsetSize = 65536;
const trie::Trie kKeywords = {
"union", "all", "optional", "match", "unwind", "as", "merge", "on", "create",
"set", "detach", "delete", "remove", "with", "distinct", "return", "order", "by",
"skip", "limit", "ascending", "asc", "descending", "desc", "where", "or", "xor",
"and", "not", "in", "starts", "ends", "contains", "is", "null", "case",
"when", "then", "else", "end", "count", "filter", "extract", "any", "none",
"single", "true", "false", "reduce", "coalesce", "user", "password", "alter", "drop",
"show", "stats", "unique", "explain", "profile", "storage", "index", "info", "exists",
"assert", "constraint", "node", "key", "dump", "database", "call", "yield", "memory",
"mb", "kb", "unlimited", "free", "procedure", "query"};
"union", "all", "optional", "match", "unwind", "as", "merge", "on", "create",
"set", "detach", "delete", "remove", "with", "distinct", "return", "order", "by",
"skip", "limit", "ascending", "asc", "descending", "desc", "where", "or", "xor",
"and", "not", "in", "starts", "ends", "contains", "is", "null", "case",
"when", "then", "else", "end", "count", "filter", "extract", "any", "none",
"single", "true", "false", "reduce", "coalesce", "user", "password", "alter", "drop",
"show", "stats", "unique", "explain", "profile", "storage", "index", "info", "exists",
"assert", "constraint", "node", "key", "dump", "database", "call", "yield", "memory",
"mb", "kb", "unlimited", "free", "procedure", "query", "free_memory", "read_file", "lock_path"};
// Unicode codepoints that are allowed at the start of the unescaped name.
const std::bitset<kBitsetSize> kUnescapedNameAllowedStarts(

View File

@ -2053,6 +2053,14 @@ TEST_P(CypherMainVisitorTest, GrantPrivilege) {
{AuthQuery::Privilege::CONSTRAINT});
check_auth_query(&ast_generator, "GRANT DUMP TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
{AuthQuery::Privilege::DUMP});
check_auth_query(&ast_generator, "GRANT REPLICATION TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
{AuthQuery::Privilege::REPLICATION});
check_auth_query(&ast_generator, "GRANT LOCK_PATH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
{AuthQuery::Privilege::LOCK_PATH});
check_auth_query(&ast_generator, "GRANT READ_FILE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
{AuthQuery::Privilege::READ_FILE});
check_auth_query(&ast_generator, "GRANT FREE_MEMORY TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
{AuthQuery::Privilege::FREE_MEMORY});
}
TEST_P(CypherMainVisitorTest, DenyPrivilege) {

View File

@ -1,6 +1,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "query/frontend/ast/ast_visitor.hpp"
#include "query/frontend/semantic/required_privileges.hpp"
#include "storage/v2/id_types.hpp"
@ -131,3 +132,20 @@ TEST_F(TestPrivilegeExtractor, DumpDatabase) {
auto *query = storage.Create<DumpQuery>();
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::DUMP));
}
TEST_F(TestPrivilegeExtractor, ReadFile) {
auto load_csv = storage.Create<LoadCsv>();
load_csv->row_var_ = IDENT("row");
auto *query = QUERY(SINGLE_QUERY(load_csv));
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::READ_FILE));
}
TEST_F(TestPrivilegeExtractor, LockPathQuery) {
auto *query = storage.Create<LockPathQuery>();
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::LOCK_PATH));
}
TEST_F(TestPrivilegeExtractor, FreeMemoryQuery) {
auto *query = storage.Create<FreeMemoryQuery>();
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::FREE_MEMORY));
}