Skip to content

Commit

Permalink
cql3: handle complex types as when decoding function permissions
Browse files Browse the repository at this point in the history
Currently, we're parsing types that appear in a function resource
using abstract_type::parse_type, which only works with simple types.
This patch changes it to db::marshal::type_parser::parse, which
can also handle collections.

We also adjust the test_grant_revoke_udf_permissions test so that
it uses both simple and complex types as parameters of the function
that we're granting/revoking permissions on.
  • Loading branch information
wmitros committed Mar 10, 2023
1 parent 438c7fd commit 9a303fd
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
3 changes: 2 additions & 1 deletion auth/resource.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "service/storage_proxy.hh"
#include "data_dictionary/user_types_metadata.hh"
#include "cql3/util.hh"
#include "db/marshal/type_parser.hh"

namespace auth {

Expand Down Expand Up @@ -231,7 +232,7 @@ std::pair<sstring, std::vector<data_type>> decode_signature(std::string_view enc
boost::split(raw_types, encoded_signature, boost::is_any_of("^"));
std::vector<data_type> decoded_types = boost::copy_range<std::vector<data_type>>(
raw_types | boost::adaptors::transformed([] (std::string_view raw_type) {
return abstract_type::parse_type(sstring(raw_type));
return db::marshal::type_parser::parse(raw_type);
})
);
return {sstring(function_name), decoded_types};
Expand Down
22 changes: 11 additions & 11 deletions test/cql-pytest/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,12 @@ def test_drop_udf_with_same_name(cql):
# Test that permissions set for user-defined functions are enforced
# Tests for ALTER are separate, because they are qualified as cassandra_bug
def test_grant_revoke_udf_permissions(cql):
schema = "a int primary key"
schema = "a int primary key, b list<int>"
user = "cassandra"
with new_test_keyspace(cql, "WITH REPLICATION = { 'class': 'SimpleStrategy', 'replication_factor': 1 }") as keyspace:
with new_test_table(cql, keyspace, schema) as table:
fun_body_lua = "(i int) CALLED ON NULL INPUT RETURNS int LANGUAGE lua AS 'return 42;'"
fun_body_java = "(i int) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return 42;'"
fun_body_lua = "(i int, l list<int>) CALLED ON NULL INPUT RETURNS int LANGUAGE lua AS 'return 42;'"
fun_body_java = "(i int, l list<int>) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return 42;'"
fun_body = fun_body_lua
try:
with new_function(cql, keyspace, fun_body) as fun:
Expand All @@ -241,28 +241,28 @@ def test_grant_revoke_udf_permissions(cql):

def create_function_idempotent():
user_session.execute(f"CREATE FUNCTION IF NOT EXISTS {keyspace}.{fun} {fun_body}")
cql.execute(f"DROP FUNCTION IF EXISTS {keyspace}.{fun}(int)")
cql.execute(f"DROP FUNCTION IF EXISTS {keyspace}.{fun}(int, list<int>)")
check_enforced(cql, username, permission='CREATE', resource=f'all functions in keyspace {keyspace}',
function=create_function_idempotent)
check_enforced(cql, username, permission='CREATE', resource='all functions',
function=create_function_idempotent)

def drop_function_idempotent():
user_session.execute(f"DROP FUNCTION IF EXISTS {keyspace}.{fun}(int)")
user_session.execute(f"DROP FUNCTION IF EXISTS {keyspace}.{fun}(int, list<int>)")
cql.execute(f"CREATE FUNCTION IF NOT EXISTS {keyspace}.{fun} {fun_body}")
for resource in [f'function {keyspace}.{fun}(int)', f'all functions in keyspace {keyspace}', 'all functions']:
for resource in [f'function {keyspace}.{fun}(int, list<int>)', f'all functions in keyspace {keyspace}', 'all functions']:
check_enforced(cql, username, permission='DROP', resource=resource, function=drop_function_idempotent)

grant(cql, 'SELECT', table, username)
for resource in [f'function {keyspace}.{fun}(int)', f'all functions in keyspace {keyspace}', 'all functions']:
for resource in [f'function {keyspace}.{fun}(int, list<int>)', f'all functions in keyspace {keyspace}', 'all functions']:
check_enforced(cql, username, permission='EXECUTE', resource=resource,
function=lambda: user_session.execute(f"SELECT {keyspace}.{fun}(a) FROM {table}"))
function=lambda: user_session.execute(f"SELECT {keyspace}.{fun}(a, b) FROM {table}"))

grant(cql, 'EXECUTE', 'ALL FUNCTIONS', username)
def grant_idempotent():
grant(user_session, 'EXECUTE', f'function {keyspace}.{fun}(int)', 'cassandra')
revoke(cql, 'EXECUTE', f'function {keyspace}.{fun}(int)', 'cassandra')
for resource in [f'function {keyspace}.{fun}(int)', f'all functions in keyspace {keyspace}', 'all functions']:
grant(user_session, 'EXECUTE', f'function {keyspace}.{fun}(int, list<int>)', 'cassandra')
revoke(cql, 'EXECUTE', f'function {keyspace}.{fun}(int, list<int>)', 'cassandra')
for resource in [f'function {keyspace}.{fun}(int, list<int>)', f'all functions in keyspace {keyspace}', 'all functions']:
check_enforced(cql, username, permission='AUTHORIZE', resource=resource, function=grant_idempotent)

# This test case is artificially extracted from the one above,
Expand Down

0 comments on commit 9a303fd

Please sign in to comment.