2020-02-04 01:15:14 +00:00
import pytest
from helpers . cluster import ClickHouseCluster
2020-05-12 23:36:39 +00:00
from helpers . test_tools import TSV
2020-02-04 01:15:14 +00:00
cluster = ClickHouseCluster ( __file__ )
2020-04-08 00:50:27 +00:00
instance = cluster . add_instance ( ' instance ' )
2020-02-04 01:15:14 +00:00
2021-07-22 13:32:51 +00:00
session_id_counter = 0
def new_session_id ( ) :
global session_id_counter
session_id_counter + = 1
return ' session # ' + str ( session_id_counter )
2020-02-04 01:15:14 +00:00
@pytest.fixture ( scope = " module " , autouse = True )
def started_cluster ( ) :
try :
cluster . start ( )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( " CREATE TABLE test_table(x UInt32, y UInt32) ENGINE = MergeTree ORDER BY tuple() " )
instance . query ( " INSERT INTO test_table VALUES (1,5), (2,10) " )
2020-02-04 01:15:14 +00:00
yield cluster
finally :
cluster . shutdown ( )
2020-02-20 04:17:44 +00:00
@pytest.fixture ( autouse = True )
2020-06-14 22:07:52 +00:00
def cleanup_after_test ( ) :
2020-02-20 04:17:44 +00:00
try :
yield
finally :
instance . query ( " DROP USER IF EXISTS A, B " )
2021-07-22 15:06:29 +00:00
instance . query ( " DROP ROLE IF EXISTS R1, R2, R3, R4 " )
2020-02-20 04:17:44 +00:00
def test_create_role ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
2020-02-20 04:17:44 +00:00
instance . query ( ' CREATE ROLE R1 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT SELECT ON test_table TO R1 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
instance . query ( ' GRANT R1 TO A ' )
assert instance . query ( " SELECT * FROM test_table " , user = ' A ' ) == " 1 \t 5 \n 2 \t 10 \n "
instance . query ( ' REVOKE R1 FROM A ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
def test_grant_role_to_role ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
2020-02-20 04:17:44 +00:00
instance . query ( ' CREATE ROLE R1 ' )
instance . query ( ' CREATE ROLE R2 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT R1 TO A ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT R2 TO R1 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT SELECT ON test_table TO R2 ' )
assert instance . query ( " SELECT * FROM test_table " , user = ' A ' ) == " 1 \t 5 \n 2 \t 10 \n "
def test_combine_privileges ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
2020-02-20 04:17:44 +00:00
instance . query ( ' CREATE ROLE R1 ' )
instance . query ( ' CREATE ROLE R2 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT R1 TO A ' )
instance . query ( ' GRANT SELECT(x) ON test_table TO R1 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' A ' )
assert instance . query ( " SELECT x FROM test_table " , user = ' A ' ) == " 1 \n 2 \n "
2020-09-16 04:26:10 +00:00
2020-02-20 04:17:44 +00:00
instance . query ( ' GRANT SELECT(y) ON test_table TO R2 ' )
instance . query ( ' GRANT R2 TO A ' )
assert instance . query ( " SELECT * FROM test_table " , user = ' A ' ) == " 1 \t 5 \n 2 \t 10 \n "
def test_admin_option ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
instance . query ( " CREATE USER B " )
2020-02-20 04:17:44 +00:00
instance . query ( ' CREATE ROLE R1 ' )
instance . query ( ' GRANT SELECT ON test_table TO R1 ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' B ' )
instance . query ( ' GRANT R1 TO A ' )
assert " Not enough privileges " in instance . query_and_get_error ( " GRANT R1 TO B " , user = ' A ' )
assert " Not enough privileges " in instance . query_and_get_error ( " SELECT * FROM test_table " , user = ' B ' )
instance . query ( ' GRANT R1 TO A WITH ADMIN OPTION ' )
instance . query ( " GRANT R1 TO B " , user = ' A ' )
assert instance . query ( " SELECT * FROM test_table " , user = ' B ' ) == " 1 \t 5 \n 2 \t 10 \n "
2020-05-12 23:36:39 +00:00
2020-07-02 00:09:57 +00:00
def test_revoke_requires_admin_option ( ) :
instance . query ( " CREATE USER A, B " )
instance . query ( " CREATE ROLE R1, R2 " )
2020-09-16 04:26:10 +00:00
2020-07-02 00:09:57 +00:00
instance . query ( " GRANT R1 TO B " )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1 TO B \n "
expected_error = " necessary to have the role R1 granted "
assert expected_error in instance . query_and_get_error ( " REVOKE R1 FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1 TO B \n "
instance . query ( " GRANT R1 TO A " )
expected_error = " granted, but without ADMIN option "
assert expected_error in instance . query_and_get_error ( " REVOKE R1 FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1 TO B \n "
instance . query ( " GRANT R1 TO A WITH ADMIN OPTION " )
instance . query ( " REVOKE R1 FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " "
instance . query ( " GRANT R1 TO B " )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1 TO B \n "
instance . query ( " REVOKE ALL FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " "
instance . query ( " GRANT R1, R2 TO B " )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1, R2 TO B \n "
expected_error = " necessary to have the role R2 granted "
assert expected_error in instance . query_and_get_error ( " REVOKE ALL FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1, R2 TO B \n "
instance . query ( " REVOKE ALL EXCEPT R2 FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R2 TO B \n "
instance . query ( " GRANT R2 TO A WITH ADMIN OPTION " )
instance . query ( " REVOKE ALL FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " "
instance . query ( " GRANT R1, R2 TO B " )
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1, R2 TO B \n "
instance . query ( " REVOKE ALL FROM B " , user = ' A ' )
assert instance . query ( " SHOW GRANTS FOR B " ) == " "
2021-07-22 13:32:51 +00:00
def test_set_role ( ) :
instance . query ( " CREATE USER A " )
instance . query ( " CREATE ROLE R1, R2 " )
instance . query ( " GRANT R1, R2 TO A " )
session_id = new_session_id ( )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R1 " , 0 , 1 ] , [ " R2 " , 0 , 1 ] ] )
instance . http_query ( ' SET ROLE R1 ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R1 " , 0 , 1 ] ] )
instance . http_query ( ' SET ROLE R2 ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R2 " , 0 , 1 ] ] )
instance . http_query ( ' SET ROLE NONE ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ ] )
instance . http_query ( ' SET ROLE DEFAULT ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R1 " , 0 , 1 ] , [ " R2 " , 0 , 1 ] ] )
2021-07-22 13:44:48 +00:00
def test_changing_default_roles_affects_new_sessions_only ( ) :
instance . query ( " CREATE USER A " )
instance . query ( " CREATE ROLE R1, R2 " )
instance . query ( " GRANT R1, R2 TO A " )
session_id = new_session_id ( )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R1 " , 0 , 1 ] , [ " R2 " , 0 , 1 ] ] )
instance . query ( ' SET DEFAULT ROLE R2 TO A ' )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : session_id } ) == TSV ( [ [ " R1 " , 0 , 0 ] , [ " R2 " , 0 , 1 ] ] )
other_session_id = new_session_id ( )
assert instance . http_query ( ' SHOW CURRENT ROLES ' , user = ' A ' , params = { ' session_id ' : other_session_id } ) == TSV ( [ [ " R2 " , 0 , 1 ] ] )
2020-05-12 23:36:39 +00:00
def test_introspection ( ) :
instance . query ( " CREATE USER A " )
instance . query ( " CREATE USER B " )
instance . query ( ' CREATE ROLE R1 ' )
instance . query ( ' CREATE ROLE R2 ' )
instance . query ( ' GRANT R1 TO A ' )
instance . query ( ' GRANT R2 TO B WITH ADMIN OPTION ' )
instance . query ( ' GRANT SELECT ON test.table TO A, R2 ' )
instance . query ( ' GRANT CREATE ON *.* TO B WITH GRANT OPTION ' )
instance . query ( ' REVOKE SELECT(x) ON test.table FROM R2 ' )
2020-09-16 04:26:10 +00:00
assert instance . query ( " SHOW ROLES " ) == TSV ( [ " R1 " , " R2 " ] )
assert instance . query ( " SHOW CREATE ROLE R1 " ) == TSV ( [ " CREATE ROLE R1 " ] )
assert instance . query ( " SHOW CREATE ROLE R2 " ) == TSV ( [ " CREATE ROLE R2 " ] )
assert instance . query ( " SHOW CREATE ROLES R1, R2 " ) == TSV ( [ " CREATE ROLE R1 " , " CREATE ROLE R2 " ] )
assert instance . query ( " SHOW CREATE ROLES " ) == TSV ( [ " CREATE ROLE R1 " , " CREATE ROLE R2 " ] )
2020-06-06 07:21:02 +00:00
2020-09-16 04:26:10 +00:00
assert instance . query ( " SHOW GRANTS FOR A " ) == TSV ( [ " GRANT SELECT ON test.table TO A " , " GRANT R1 TO A " ] )
assert instance . query ( " SHOW GRANTS FOR B " ) == TSV (
[ " GRANT CREATE ON *.* TO B WITH GRANT OPTION " , " GRANT R2 TO B WITH ADMIN OPTION " ] )
2020-05-12 23:36:39 +00:00
assert instance . query ( " SHOW GRANTS FOR R1 " ) == " "
2020-09-16 04:26:10 +00:00
assert instance . query ( " SHOW GRANTS FOR R2 " ) == TSV (
[ " GRANT SELECT ON test.table TO R2 " , " REVOKE SELECT(x) ON test.table FROM R2 " ] )
assert instance . query ( " SHOW GRANTS " , user = ' A ' ) == TSV ( [ " GRANT SELECT ON test.table TO A " , " GRANT R1 TO A " ] )
assert instance . query ( " SHOW GRANTS " , user = ' B ' ) == TSV (
[ " GRANT CREATE ON *.* TO B WITH GRANT OPTION " , " GRANT R2 TO B WITH ADMIN OPTION " ] )
assert instance . query ( " SHOW CURRENT ROLES " , user = ' A ' ) == TSV ( [ [ " R1 " , 0 , 1 ] ] )
assert instance . query ( " SHOW CURRENT ROLES " , user = ' B ' ) == TSV ( [ [ " R2 " , 1 , 1 ] ] )
assert instance . query ( " SHOW ENABLED ROLES " , user = ' A ' ) == TSV ( [ [ " R1 " , 0 , 1 , 1 ] ] )
assert instance . query ( " SHOW ENABLED ROLES " , user = ' B ' ) == TSV ( [ [ " R2 " , 1 , 1 , 1 ] ] )
expected_access1 = " CREATE ROLE R1 \n " \
2020-06-10 23:08:37 +00:00
" CREATE ROLE R2 \n "
expected_access2 = " GRANT R1 TO A \n "
expected_access3 = " GRANT R2 TO B WITH ADMIN OPTION "
assert expected_access1 in instance . query ( " SHOW ACCESS " )
assert expected_access2 in instance . query ( " SHOW ACCESS " )
assert expected_access3 in instance . query ( " SHOW ACCESS " )
2020-09-16 04:26:10 +00:00
assert instance . query ( " SELECT name, storage from system.roles WHERE name IN ( ' R1 ' , ' R2 ' ) ORDER BY name " ) == \
TSV ( [ [ " R1 " , " local directory " ] ,
[ " R2 " , " local directory " ] ] )
assert instance . query (
2022-02-03 17:40:15 +00:00
" SELECT * from system.grants WHERE user_name IN ( ' A ' , ' B ' ) OR role_name IN ( ' R1 ' , ' R2 ' ) ORDER BY user_name, role_name, access_type, database, table, column, is_partial_revoke, grant_option " ) == \
2020-10-02 16:54:07 +00:00
TSV ( [ [ " A " , " \\ N " , " SELECT " , " test " , " table " , " \\ N " , 0 , 0 ] ,
[ " B " , " \\ N " , " CREATE " , " \\ N " , " \\ N " , " \\ N " , 0 , 1 ] ,
2022-02-03 17:40:15 +00:00
[ " \\ N " , " R2 " , " SELECT " , " test " , " table " , " x " , 1 , 0 ] ,
[ " \\ N " , " R2 " , " SELECT " , " test " , " table " , " \\ N " , 0 , 0 ] ] )
2020-09-16 04:26:10 +00:00
assert instance . query (
" SELECT * from system.role_grants WHERE user_name IN ( ' A ' , ' B ' ) OR role_name IN ( ' R1 ' , ' R2 ' ) ORDER BY user_name, role_name, granted_role_name " ) == \
2020-10-02 16:54:07 +00:00
TSV ( [ [ " A " , " \\ N " , " R1 " , 1 , 0 ] ,
[ " B " , " \\ N " , " R2 " , 1 , 1 ] ] )
2020-09-16 04:26:10 +00:00
assert instance . query ( " SELECT * from system.current_roles ORDER BY role_name " , user = ' A ' ) == TSV ( [ [ " R1 " , 0 , 1 ] ] )
assert instance . query ( " SELECT * from system.current_roles ORDER BY role_name " , user = ' B ' ) == TSV ( [ [ " R2 " , 1 , 1 ] ] )
assert instance . query ( " SELECT * from system.enabled_roles ORDER BY role_name " , user = ' A ' ) == TSV ( [ [ " R1 " , 0 , 1 , 1 ] ] )
assert instance . query ( " SELECT * from system.enabled_roles ORDER BY role_name " , user = ' B ' ) == TSV ( [ [ " R2 " , 1 , 1 , 1 ] ] )
2021-07-22 15:06:29 +00:00
def test_function_current_roles ( ) :
instance . query ( " CREATE USER A " )
instance . query ( ' CREATE ROLE R1, R2, R3, R4 ' )
instance . query ( ' GRANT R4 TO R2 ' )
instance . query ( ' GRANT R1,R2,R3 TO A ' )
session_id = new_session_id ( )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' , ' R4 ' ] \n "
instance . http_query ( ' SET ROLE R1 ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' ] \t [ ' R1 ' ] \n "
instance . http_query ( ' SET ROLE R2 ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R2 ' ] \t [ ' R2 ' , ' R4 ' ] \n "
instance . http_query ( ' SET ROLE NONE ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [] \t [] \n "
instance . http_query ( ' SET ROLE DEFAULT ' , user = ' A ' , params = { ' session_id ' : session_id } )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' , ' R4 ' ] \n "
instance . query ( ' SET DEFAULT ROLE R2 TO A ' )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R2 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' ] \t [ ' R1 ' , ' R2 ' , ' R3 ' , ' R4 ' ] \n "
instance . query ( ' REVOKE R3 FROM A ' )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R2 ' ] \t [ ' R1 ' , ' R2 ' ] \t [ ' R1 ' , ' R2 ' , ' R4 ' ] \n "
instance . query ( ' REVOKE R2 FROM A ' )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [] \t [ ' R1 ' ] \t [ ' R1 ' ] \n "
instance . query ( ' SET DEFAULT ROLE ALL TO A ' )
assert instance . http_query ( ' SELECT defaultRoles(), currentRoles(), enabledRoles() ' , user = ' A ' , params = { ' session_id ' : session_id } ) == " [ ' R1 ' ] \t [ ' R1 ' ] \t [ ' R1 ' ] \n "