Skip to content

Commit

Permalink
Fix tests for CASSANDRA-18252 - removal of scripted UDFs
Browse files Browse the repository at this point in the history
patch by Ekaterina Dimitrova; reviewed by Michael Semb Wever for CASSANDRA-18252
  • Loading branch information
ekaterinadimitrova2 committed Feb 12, 2023
1 parent 049703f commit bfec30a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 38 deletions.
93 changes: 71 additions & 22 deletions auth_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ def fixture_dtest_setup_overrides(self, dtest_config):
@jira_ticket CASSANDRA-7653
"""
dtest_setup_overrides = DTestSetupOverrides()
if dtest_config.cassandra_version_from_build >= '3.0':
if '3.0' <= dtest_config.cassandra_version_from_build < '4.2':
dtest_setup_overrides.cluster_options = ImmutableMapping({'enable_user_defined_functions': 'true',
'enable_scripted_user_defined_functions': 'true'})
else:
Expand Down Expand Up @@ -1364,11 +1364,18 @@ def test_creator_of_db_resource_granted_all_permissions(self):
as_mike.execute("CREATE KEYSPACE ks WITH replication = {'class':'SimpleStrategy', 'replication_factor':1}")
as_mike.execute("CREATE TABLE ks.cf (id int primary key, val int)")
as_mike.execute("CREATE ROLE role1 WITH PASSWORD = '11111' AND SUPERUSER = false AND LOGIN = true")
as_mike.execute("""CREATE FUNCTION ks.state_function_1(a int, b int)
CALLED ON NULL INPUT
RETURNS int
LANGUAGE javascript
AS ' a + b'""")
if self.cluster.version() < LooseVersion('4.2'):
as_mike.execute("""CREATE FUNCTION ks.state_function_1(a int, b int)
CALLED ON NULL INPUT
RETURNS int
LANGUAGE javascript
AS ' a + b'""")
else:
as_mike.execute("""CREATE FUNCTION ks.state_function_1(a int, b int)
CALLED ON NULL INPUT
RETURNS int
LANGUAGE java
AS ' return a + b;'""")
as_mike.execute("""CREATE AGGREGATE ks.simple_aggregate_1(int)
SFUNC state_function_1
STYPE int
Expand Down Expand Up @@ -1654,7 +1661,10 @@ def test_filter_granted_permissions_by_resource_type(self):
self.superuser.execute("CREATE TABLE ks.cf (id int primary key, val int)")
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND SUPERUSER = false AND LOGIN = true")
self.superuser.execute("CREATE ROLE role1 WITH SUPERUSER = false AND LOGIN = false")
self.superuser.execute("CREATE FUNCTION ks.state_func(a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'a+b'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.state_func(a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'a+b'")
else:
self.superuser.execute("CREATE FUNCTION ks.state_func(a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS ' return a+b;'")
self.superuser.execute("CREATE AGGREGATE ks.agg_func(int) SFUNC state_func STYPE int")

# GRANT ALL ON ALL KEYSPACES grants Permission.ALL_DATA
Expand Down Expand Up @@ -2125,8 +2135,12 @@ def test_grant_revoke_udf_permissions(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.\"plusOne\" ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.\"plusOne\" ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("CREATE FUNCTION ks.\"plusOne\" ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")

# grant / revoke on a specific function
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
Expand Down Expand Up @@ -2170,7 +2184,10 @@ def test_grant_revoke_are_idempotent(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
self.assert_permissions_listed([("mike", "<function ks.plus_one(int)>", "EXECUTE")],
Expand Down Expand Up @@ -2198,8 +2215,12 @@ def test_function_resource_hierarchy_permissions(self):
self.superuser.execute("INSERT INTO ks.t1 (k,v) values (1,1)")
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("GRANT SELECT ON ks.t1 TO mike")
self.superuser.execute("CREATE FUNCTION ks.func_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.func_two ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.func_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.func_two ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.func_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("CREATE FUNCTION ks.func_two ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")

as_mike = self.get_session(user='mike', password='12345')
select_one = "SELECT k, v, ks.func_one(v) FROM ks.t1 WHERE k = 1"
Expand Down Expand Up @@ -2253,12 +2274,18 @@ def test_udf_permissions_validation(self):
* Verify mike can create a new UDF iff he has the CREATE permission
"""
self.setup_table()
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
as_mike = self.get_session(user='mike', password='12345')

# can't replace an existing function without ALTER permission on the parent ks
cql = "CREATE OR REPLACE FUNCTION ks.plus_one( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript as '1 + input'"
if self.cluster.version() < LooseVersion('4.2'):
cql = "CREATE OR REPLACE FUNCTION ks.plus_one( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript as '1 + input'"
else:
cql = "CREATE OR REPLACE FUNCTION ks.plus_one( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java as 'return 1 + input;'"
assert_unauthorized(as_mike, cql,
r"User mike has no ALTER permission on <function ks.plus_one\(int\)> or any of its parents")
self.superuser.execute("GRANT ALTER ON FUNCTION ks.plus_one(int) TO mike")
Expand Down Expand Up @@ -2298,7 +2325,10 @@ def test_udf_permissions_validation(self):
InvalidRequest)

# can't create a new function without CREATE on the parent keyspace's collection of functions
cql = "CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'"
if self.cluster.version() < LooseVersion('4.2'):
cql = "CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'"
else:
cql = "CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'"
assert_unauthorized(as_mike, cql,
"User mike has no CREATE permission on <all functions in ks> or any of its parents")
self.superuser.execute("GRANT CREATE ON ALL FUNCTIONS IN KEYSPACE ks TO mike")
Expand All @@ -2315,7 +2345,10 @@ def test_drop_role_cleans_up_udf_permissions(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
self.superuser.execute("GRANT EXECUTE ON ALL FUNCTIONS IN KEYSPACE ks TO mike")
self.superuser.execute("GRANT EXECUTE ON ALL FUNCTIONS TO mike")
Expand Down Expand Up @@ -2343,7 +2376,10 @@ def test_drop_function_and_keyspace_cleans_up_udf_permissions(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
self.superuser.execute("GRANT EXECUTE ON ALL FUNCTIONS IN KEYSPACE ks TO mike")

Expand Down Expand Up @@ -2371,8 +2407,12 @@ def test_udf_with_overloads_permissions(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input double ) CALLED ON NULL INPUT RETURNS double LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input double ) CALLED ON NULL INPUT RETURNS double LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input double ) CALLED ON NULL INPUT RETURNS double LANGUAGE java AS 'return input + 1;'")

# grant execute on one variant
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.plus_one(int) TO mike")
Expand Down Expand Up @@ -2414,7 +2454,10 @@ def test_drop_keyspace_cleans_up_function_level_permissions(self):
"""
self.setup_table()
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("CREATE FUNCTION ks.state_func (a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'a + b'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.state_func (a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'a + b'")
else:
self.superuser.execute("CREATE FUNCTION ks.state_func (a int, b int) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return a + b;'")
self.superuser.execute("CREATE AGGREGATE ks.agg_func (int) SFUNC state_func STYPE int")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.state_func(int, int) TO mike")
self.superuser.execute("GRANT EXECUTE ON FUNCTION ks.agg_func(int) TO mike")
Expand Down Expand Up @@ -2467,7 +2510,10 @@ def verify_udf_permissions(self, cql):
@param cql The statement to verify. Should contain the UDF ks.plus_one
"""
self.setup_table()
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("GRANT ALL PERMISSIONS ON ks.t1 TO mike")
self.superuser.execute("INSERT INTO ks.t1 (k,v) values (1,1)")
Expand All @@ -2488,7 +2534,10 @@ def test_inheritence_of_udf_permissions(self):
self.setup_table()
self.superuser.execute("CREATE ROLE function_user")
self.superuser.execute("GRANT EXECUTE ON ALL FUNCTIONS IN KEYSPACE ks TO function_user")
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
if self.cluster.version() < LooseVersion('4.2'):
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE javascript AS 'input + 1'")
else:
self.superuser.execute("CREATE FUNCTION ks.plus_one ( input int ) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return input + 1;'")
self.superuser.execute("INSERT INTO ks.t1 (k,v) VALUES (1,1)")
self.superuser.execute("CREATE ROLE mike WITH PASSWORD = '12345' AND LOGIN = true")
self.superuser.execute("GRANT SELECT ON ks.t1 TO mike")
Expand Down
2 changes: 1 addition & 1 deletion cqlsh_tests/test_cqlsh.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class TestCqlsh(Tester, CqlshMixin):
def fixture_dtest_setup_overrides(self, dtest_config):
dtest_setup_overrides = DTestSetupOverrides()

if dtest_config.cassandra_version_from_build >= '3.0':
if '3.0' <= dtest_config.cassandra_version_from_build < '4.2':
dtest_setup_overrides.cluster_options = ImmutableMapping({'enable_user_defined_functions': 'true',
'enable_scripted_user_defined_functions': 'true'})
else:
Expand Down
4 changes: 3 additions & 1 deletion schema_metadata_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,9 @@ def fixture_set_cluster_settings(self, fixture_dtest_setup):
cluster = fixture_dtest_setup.cluster
cluster.schema_event_refresh_window = 0

if cluster.version() >= '3.0':
if cluster.version() >= '4.2':
cluster.set_configuration_options({'enable_user_defined_functions': 'true'})
elif cluster.version() >= '3.0':
cluster.set_configuration_options({'enable_user_defined_functions': 'true',
'enable_scripted_user_defined_functions': 'true'})
elif cluster.version() >= '2.2':
Expand Down
12 changes: 10 additions & 2 deletions upgrade_tests/upgrade_through_versions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .upgrade_manifest import (build_upgrade_pairs,
current_2_1_x, current_2_2_x, current_3_0_x,
indev_3_11_x,
current_3_11_x, indev_trunk, CASSANDRA_4_0)
current_3_11_x, indev_trunk, CASSANDRA_4_0, CASSANDRA_4_2)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -434,7 +434,6 @@ def upgrade_scenario(self, populate=True, create_schema=True, rolling=False, aft
self._check_on_subprocs(self.fixture_dtest_setup.subprocs)
logger.debug('Successfully upgraded %d of %d nodes to %s' %
(num + 1, len(self.cluster.nodelist()), version_meta.version))

self.cluster.set_install_dir(version=version_meta.version)
self.install_nodetool_legacy_parsing()
self.fixture_dtest_setup.reinitialize_cluster_for_different_version()
Expand Down Expand Up @@ -527,6 +526,8 @@ def upgrade_to_version(self, version_meta, partial=False, nodes=None, internode_
logger.debug("Set new cassandra dir for %s: %s" % (node.name, node.get_install_dir()))
if internode_ssl and (LooseVersion(version_meta.family) >= CASSANDRA_4_0):
node.set_configuration_options({'server_encryption_options': {'enabled': True, 'enable_legacy_ssl_storage_port': True}})
if LooseVersion(version_meta.family) >= CASSANDRA_4_2:
node.set_configuration_options({'enable_scripted_user_defined_functions': 'false'})

# hacky? yes. We could probably extend ccm to allow this publicly.
# the topology file needs to be written before any nodes are started
Expand Down Expand Up @@ -776,6 +777,10 @@ def _bootstrap_new_node(self):
# Check we can bootstrap a new node on the upgraded cluster:
logger.debug("Adding a node to the cluster")
nnode = new_node(self.cluster, remote_debug_port=str(2000 + len(self.cluster.nodes)))

if nnode.get_cassandra_version() >= '4.2':
nnode.set_configuration_options({'enable_scripted_user_defined_functions': 'false'})

nnode.start(use_jna=True, wait_other_notice=240, wait_for_binary_proto=True)
self._write_values()
self._increment_counters()
Expand All @@ -787,6 +792,9 @@ def _bootstrap_new_node_multidc(self):
logger.debug("Adding a node to the cluster")
nnode = new_node(self.cluster, remote_debug_port=str(2000 + len(self.cluster.nodes)), data_center='dc2')

if nnode.get_cassandra_version() >= '4.2':
nnode.set_configuration_options({'enable_scripted_user_defined_functions': 'false'})

nnode.start(use_jna=True, wait_other_notice=240, wait_for_binary_proto=True)
self._write_values()
self._increment_counters()
Expand Down
Loading

0 comments on commit bfec30a

Please sign in to comment.