2020-02-04 01:15:14 +00:00
import pytest
2022-05-05 13:11:40 +00:00
from helpers . client import QueryRuntimeException
2020-02-04 01:15:14 +00:00
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__ )
2022-03-22 16:39:58 +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
2022-03-22 16:39:58 +00:00
2021-07-22 13:32:51 +00:00
def new_session_id ( ) :
global session_id_counter
session_id_counter + = 1
2022-03-22 16:39:58 +00:00
return " session # " + str ( session_id_counter )
2021-07-22 13:32:51 +00:00
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
2022-03-22 16:39:58 +00:00
instance . query (
" CREATE TABLE test_table(x UInt32, y UInt32) ENGINE = MergeTree ORDER BY tuple() "
)
2020-02-20 04:17:44 +00:00
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 " )
2022-03-22 16:39:58 +00:00
instance . query ( " CREATE ROLE R1 " )
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
assert " Not enough privileges " in instance . query_and_get_error (
" SELECT * FROM test_table " , user = " A "
)
2020-09-16 04:26:10 +00:00
2022-03-22 16:39:58 +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 "
)
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
instance . query ( " GRANT R1 TO A " )
assert instance . query ( " SELECT * FROM test_table " , user = " A " ) == " 1 \t 5 \n 2 \t 10 \n "
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE R1 FROM A " )
assert " Not enough privileges " in instance . query_and_get_error (
" SELECT * FROM test_table " , user = " A "
)
2020-02-20 04:17:44 +00:00
def test_grant_role_to_role ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
2022-03-22 16:39:58 +00:00
instance . query ( " CREATE ROLE R1 " )
instance . query ( " CREATE ROLE R2 " )
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
assert " Not enough privileges " in instance . query_and_get_error (
" SELECT * FROM test_table " , user = " A "
)
2020-09-16 04:26:10 +00:00
2022-03-22 16:39:58 +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
2022-03-22 16:39:58 +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
2022-03-22 16:39:58 +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 "
2020-02-20 04:17:44 +00:00
def test_combine_privileges ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
2022-03-22 16:39:58 +00:00
instance . query ( " CREATE ROLE R1 " )
instance . query ( " CREATE ROLE R2 " )
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
assert " Not enough privileges " in instance . query_and_get_error (
" SELECT * FROM test_table " , user = " A "
)
2020-09-16 04:26:10 +00:00
2022-03-22 16:39:58 +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
2022-03-22 16:39:58 +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 "
2020-02-20 04:17:44 +00:00
def test_admin_option ( ) :
2020-03-18 14:12:09 +00:00
instance . query ( " CREATE USER A " )
instance . query ( " CREATE USER B " )
2022-03-22 16:39:58 +00:00
instance . query ( " CREATE ROLE R1 " )
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +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 = " B "
)
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
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 "
)
2020-02-20 04:17:44 +00:00
2022-03-22 16:39:58 +00:00
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 "
2022-03-22 16:39:58 +00:00
assert expected_error in instance . query_and_get_error ( " REVOKE R1 FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
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 "
2022-03-22 16:39:58 +00:00
assert expected_error in instance . query_and_get_error ( " REVOKE R1 FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1 TO B \n "
instance . query ( " GRANT R1 TO A WITH ADMIN OPTION " )
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE R1 FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
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 "
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE ALL FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
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 "
2022-03-22 16:39:58 +00:00
assert expected_error in instance . query_and_get_error ( " REVOKE ALL FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R1, R2 TO B \n "
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE ALL EXCEPT R2 FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
assert instance . query ( " SHOW GRANTS FOR B " ) == " GRANT R2 TO B \n "
instance . query ( " GRANT R2 TO A WITH ADMIN OPTION " )
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE ALL FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
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 "
2022-03-22 16:39:58 +00:00
instance . query ( " REVOKE ALL FROM B " , user = " A " )
2020-07-02 00:09:57 +00:00
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 ( )
2022-03-22 16:39:58 +00:00
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:32:51 +00:00
2022-03-22 16:39:58 +00:00
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 ] ] )
2021-07-22 13:32:51 +00:00
2022-03-22 16:39:58 +00:00
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 ] ] )
2021-07-22 13:32:51 +00:00
2022-03-22 16:39:58 +00:00
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 ( [ ] )
2021-07-22 13:32:51 +00:00
2022-03-22 16:39:58 +00:00
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:32:51 +00:00
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 ( )
2022-03-22 16:39:58 +00:00
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 ] ] )
2021-07-22 13:44:48 +00:00
other_session_id = new_session_id ( )
2022-03-22 16:39:58 +00:00
assert instance . http_query (
" SHOW CURRENT ROLES " , user = " A " , params = { " session_id " : other_session_id }
) == TSV ( [ [ " R2 " , 0 , 1 ] ] )
2021-07-22 13:44:48 +00:00
2020-05-12 23:36:39 +00:00
def test_introspection ( ) :
instance . query ( " CREATE USER A " )
instance . query ( " CREATE USER B " )
2022-03-22 16:39:58 +00:00
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-05-12 23:36:39 +00:00
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 " ] )
2022-03-22 16:39:58 +00:00
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 " ]
)
assert instance . query ( " SHOW GRANTS FOR A " ) == TSV (
[ " GRANT SELECT ON test.table TO A " , " GRANT R1 TO A " ]
)
2020-09-16 04:26:10 +00:00
assert instance . query ( " SHOW GRANTS FOR B " ) == TSV (
2022-03-22 16:39:58 +00:00
[
" 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 (
2022-03-22 16:39:58 +00:00
[ " 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 " ]
)
2022-05-05 13:11:40 +00:00
assert instance . query ( " SHOW GRANTS FOR R1 " , user = " A " ) == TSV ( [ ] )
with pytest . raises ( QueryRuntimeException , match = " Not enough privileges " ) :
assert instance . query ( " SHOW GRANTS FOR R2 " , user = " A " )
2022-03-22 16:39:58 +00:00
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 " " CREATE ROLE R2 \n "
2020-06-10 23:08:37 +00:00
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 " )
2022-03-22 16:39:58 +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 " ] ] )
2020-09-16 04:26:10 +00:00
assert instance . query (
2022-03-22 16:39:58 +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 "
) == TSV (
[
[ " A " , " \\ N " , " SELECT " , " test " , " table " , " \\ N " , 0 , 0 ] ,
[ " B " , " \\ N " , " CREATE " , " \\ N " , " \\ N " , " \\ N " , 0 , 1 ] ,
[ " \\ 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 (
2022-03-22 16:39:58 +00:00
" 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 "
) == TSV ( [ [ " A " , " \\ N " , " R1 " , 1 , 0 ] , [ " B " , " \\ N " , " R2 " , 1 , 1 ] ] )
2020-09-16 04:26:10 +00:00
2022-03-22 16:39:58 +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 " )
2022-03-22 16:39:58 +00:00
instance . query ( " CREATE ROLE R1, R2, R3, R4 " )
instance . query ( " GRANT R4 TO R2 " )
instance . query ( " GRANT R1,R2,R3 TO A " )
2021-07-22 15:06:29 +00:00
session_id = new_session_id ( )
2022-03-22 16:39:58 +00:00
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 "
)