2024-09-27 10:19:39 +00:00
|
|
|
import re
|
|
|
|
|
2020-12-21 23:58:54 +00:00
|
|
|
import pytest
|
2024-02-02 09:29:55 +00:00
|
|
|
|
2020-12-21 23:58:54 +00:00
|
|
|
from helpers.cluster import ClickHouseCluster
|
|
|
|
|
|
|
|
cluster = ClickHouseCluster(__file__)
|
2022-07-18 12:25:14 +00:00
|
|
|
instance = cluster.add_instance("instance")
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
|
|
|
def started_cluster():
|
|
|
|
try:
|
|
|
|
cluster.start()
|
|
|
|
yield cluster
|
|
|
|
finally:
|
|
|
|
cluster.shutdown()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def cleanup_after_test():
|
|
|
|
instance.query("CREATE USER OR REPLACE A")
|
|
|
|
yield
|
|
|
|
instance.query("DROP TABLE IF EXISTS table1")
|
|
|
|
instance.query("DROP TABLE IF EXISTS table2")
|
|
|
|
|
|
|
|
|
|
|
|
def test_select_single_column():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(d DATE, a String, b UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT a FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(a) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(a) ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_select_single_column_with_table_grant():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(d DATE, a String, b UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT a FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(a) ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_select_all_columns():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(d DATE, a String, b UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(d, a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(d) ON default.table1 TO A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(d, a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(a) ON default.table1 TO A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(d, a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(b) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
|
|
|
|
def test_select_all_columns_with_table_grant():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(d DATE, a String, b UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(d, a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
|
|
|
|
def test_alias():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(x Int32, y Int32) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT x, y, x + y AS s FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(x, y) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(x, y) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
|
|
|
|
def test_alias_columns():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(x Int32, y Int32, s Int32 ALIAS x + y) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(x, y) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(x,y) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
select_query = "SELECT s FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(s) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-05-05 18:52:20 +00:00
|
|
|
|
2020-12-21 23:58:54 +00:00
|
|
|
instance.query("GRANT SELECT(s) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(x,y) ON default.table1 FROM A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
|
|
|
|
def test_materialized_columns():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(x Int32, y Int32, p Int32 MATERIALIZED x * y) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(x, y) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(x,y) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
select_query = "SELECT p FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(p) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
|
|
|
|
2020-12-21 23:58:54 +00:00
|
|
|
instance.query("GRANT SELECT(p) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(x,y) ON default.table1 FROM A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
|
|
|
|
def test_select_join():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(d DATE, a String, b UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table2(d DATE, x UInt32, y UInt8) ENGINE = MergeTree ORDER BY d"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1 JOIN table2 USING(d)"
|
2024-02-02 09:29:55 +00:00
|
|
|
|
|
|
|
def match_error(err, columns, table):
|
|
|
|
"""Check if the error message contains the expected table and columns"""
|
|
|
|
|
|
|
|
match = re.search(
|
|
|
|
r"it's necessary to have the grant SELECT\((.*)\) ON default\.(\w+)", err
|
|
|
|
)
|
|
|
|
if not match:
|
|
|
|
return False
|
|
|
|
if match.group(2) != table:
|
|
|
|
return False
|
|
|
|
assert set(match.group(1).split(", ")) == set(
|
|
|
|
columns.split(", ")
|
|
|
|
), f"expected {columns} in {err}"
|
|
|
|
return True
|
|
|
|
|
|
|
|
response = instance.query_and_get_error(select_query, user="A")
|
|
|
|
table1_match = match_error(response, "d, a, b", "table1")
|
|
|
|
table2_match = match_error(response, "d, x, y", "table2")
|
|
|
|
assert table1_match or table2_match, response
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(d, x, y) ON default.table2 TO A")
|
2024-02-02 09:29:55 +00:00
|
|
|
response = instance.query_and_get_error(select_query, user="A")
|
|
|
|
assert match_error(response, "d, a, b", "table1")
|
2020-12-21 23:58:54 +00:00
|
|
|
|
2024-02-02 09:29:55 +00:00
|
|
|
response = instance.query_and_get_error(select_query, user="A")
|
2020-12-21 23:58:54 +00:00
|
|
|
instance.query("GRANT SELECT(d, a, b) ON default.table1 TO A")
|
2024-02-02 09:29:55 +00:00
|
|
|
|
2020-12-21 23:58:54 +00:00
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT ON default.table2 FROM A")
|
2024-02-02 09:29:55 +00:00
|
|
|
response = instance.query_and_get_error(select_query, user="A")
|
|
|
|
assert match_error(response, "d, x, y", "table2")
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_select_union():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(a String, b UInt8) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table2(a String, b UInt8) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT * FROM table1 UNION ALL SELECT * FROM table2"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(a, b) ON default.table1 TO A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table2"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-21 23:58:54 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(a, b) ON default.table2 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == ""
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2020-12-21 23:58:54 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-18 20:09:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_select_count():
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(x String, y UInt8) ENGINE = MergeTree ORDER BY tuple()"
|
|
|
|
)
|
|
|
|
|
|
|
|
select_query = "SELECT count() FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT for at least one column on default.table1"
|
2020-12-18 20:09:39 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-18 20:09:39 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(x) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "0\n"
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(x) ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT for at least one column on default.table1"
|
2020-12-18 20:09:39 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-18 20:09:39 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(y) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "0\n"
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(y) ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT for at least one column on default.table1"
|
2020-12-18 20:09:39 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2020-12-18 20:09:39 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "0\n"
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_select_where():
|
|
|
|
# User should have grants for the columns used in WHERE.
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(a String, b UInt8) ENGINE = MergeTree ORDER BY b"
|
|
|
|
)
|
|
|
|
instance.query("INSERT INTO table1 VALUES ('xxx', 0), ('yyy', 1), ('zzz', 0)")
|
|
|
|
instance.query("GRANT SELECT(a) ON default.table1 TO A")
|
|
|
|
|
|
|
|
select_query = "SELECT a FROM table1 WHERE b = 0"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(b) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "xxx\nzzz\n"
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "xxx\nzzz\n"
|
|
|
|
|
|
|
|
|
|
|
|
def test_select_prewhere():
|
|
|
|
# User should have grants for the columns used in PREWHERE.
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(a String, b UInt8) ENGINE = MergeTree ORDER BY b"
|
|
|
|
)
|
|
|
|
instance.query("INSERT INTO table1 VALUES ('xxx', 0), ('yyy', 1), ('zzz', 0)")
|
|
|
|
instance.query("GRANT SELECT(a) ON default.table1 TO A")
|
|
|
|
|
|
|
|
select_query = "SELECT a FROM table1 PREWHERE b = 0"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(b) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "xxx\nzzz\n"
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a, b) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "xxx\nzzz\n"
|
|
|
|
|
|
|
|
|
|
|
|
def test_select_with_row_policy():
|
|
|
|
# Normal users should not aware of the existence of row policy filters.
|
|
|
|
instance.query(
|
|
|
|
"CREATE TABLE table1(a String, b UInt8) ENGINE = MergeTree ORDER BY b"
|
|
|
|
)
|
|
|
|
instance.query("INSERT INTO table1 VALUES ('xxx', 0), ('yyy', 1), ('zzz', 0)")
|
|
|
|
instance.query("CREATE ROW POLICY pol1 ON table1 USING b = 0 TO A")
|
|
|
|
|
|
|
|
select_query = "SELECT a FROM table1"
|
|
|
|
select_query2 = "SELECT count() FROM table1"
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
|
|
|
)
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT for at least one column on default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query2, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-06-23 08:08:58 +00:00
|
|
|
|
|
|
|
instance.query("GRANT SELECT(a) ON default.table1 TO A")
|
|
|
|
assert instance.query(select_query, user="A") == "xxx\nzzz\n"
|
|
|
|
assert instance.query(select_query2, user="A") == "2\n"
|
|
|
|
|
|
|
|
instance.query("REVOKE SELECT(a) ON default.table1 FROM A")
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT(a) ON default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query, user="A")
|
|
|
|
)
|
|
|
|
assert (
|
2023-08-06 12:48:20 +00:00
|
|
|
"it's necessary to have the grant SELECT for at least one column on default.table1"
|
2021-06-23 08:08:58 +00:00
|
|
|
in instance.query_and_get_error(select_query2, user="A")
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|