6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00

Added/Updated tests\bugs\core_5887_trusted_role_test.py: One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov).

This commit is contained in:
pavel-zotov 2024-08-02 12:04:17 +03:00
parent 9c70256e56
commit 3f3b172866

View File

@ -1,151 +1,180 @@
#coding:utf-8 #coding:utf-8
""" """
ID: issue-6145-B ID: issue-6145-B
ISSUE: 6145 ISSUE: 6145
TITLE: Allow the use of management statements in PSQL blocks TITLE: Allow the use of management statements in PSQL blocks
DESCRIPTION: DESCRIPTION:
Role can be set as TRUSTED when following conditions are true: Role can be set as TRUSTED when following conditions are true:
* BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place; * BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place;
* current OS user has admin rights; * current OS user has admin rights;
* OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET); * OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET);
* Two mappings are created (both uses plugin win_sspi): * Two mappings are created (both uses plugin win_sspi):
** from any user to user; ** from any user to user;
** from predefined_group domain_any_rid_admins to role <role_to_be_trusted> ** from predefined_group domain_any_rid_admins to role <role_to_be_trusted>
Connect to database should be done in form: CONNECT '<computername>:<our_database>' role <role_to_be_trusted>', Connect to database should be done in form: CONNECT '<computername>:<our_database>' role <role_to_be_trusted>',
and after this we can user 'SET TRUSTED ROLE' statement. and after this we can user 'SET TRUSTED ROLE' statement.
This test checks that statement 'SET TRUSTED ROLE' can be used within PSQL block rather than as DSQL. This test checks that statement 'SET TRUSTED ROLE' can be used within PSQL block rather than as DSQL.
JIRA: CORE-5887 JIRA: CORE-5887
FBTEST: bugs.core_5887_trusted_role FBTEST: bugs.core_5887_trusted_role
NOTES: NOTES:
[15.08.2022] pzotov [15.08.2022] pzotov
Checked on 5.0.0.623, 4.0.1.2692. Checked on 5.0.0.623, 4.0.1.2692.
[04.03.2023] pzotov [04.03.2023] pzotov
Computer name must be converted to UPPERCASE, otherwise test fails. Computer name must be converted to UPPERCASE, otherwise test fails.
""" [02.08.2024] pzotov
One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov).
import os Checked on Windows 6.0.0.406, 5.0.1.1469, 4.0.5.3139
import socket """
import getpass
import os
import pytest import ctypes
from firebird.qa import * import socket
import getpass
for v in ('ISC_USER','ISC_PASSWORD'):
try: import pytest
del os.environ[ v ] from firebird.qa import *
except KeyError as e:
pass for v in ('ISC_USER','ISC_PASSWORD'):
try:
THIS_COMPUTER_NAME = socket.gethostname().upper() del os.environ[ v ]
CURRENT_WIN_ADMIN = getpass.getuser() except KeyError as e:
pass
db = db_factory()
act = python_act('db', substitutions=[('\t+', ' '), ('TCPv(4|6)', 'TCP')]) THIS_COMPUTER_NAME = socket.gethostname().upper()
CURRENT_WIN_ADMIN = getpass.getuser()
tmp_role_senior = role_factory('db', name='tmp_role_5887_senior')
tmp_role_junior = role_factory('db', name='tmp_role_5887_junior') db = db_factory()
act = python_act('db', substitutions=[('\t+', ' '), ('TCPv(4|6)', 'TCP')])
@pytest.mark.version('>=4.0')
@pytest.mark.platform('Windows') tmp_role_senior = role_factory('db', name='tmp_role_5887_senior')
def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys): tmp_role_junior = role_factory('db', name='tmp_role_5887_junior')
sql_init = f""" #----------------------------------------------------------
create table test(id int);
grant select on test to role {tmp_role_senior.name}; def is_admin():
commit; # https://serverfault.com/questions/29659/crossplatform-way-to-check-admin-rights-in-python-script
# Checked on Windows 10.
-- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get try:
-- Statement failed, SQLSTATE = 28000 /Missing security context for <test_database> is_admin = os.getuid() == 0
-- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB: except AttributeError:
create or alter mapping trusted_auth using plugin win_sspi from any user to user; is_admin = ctypes.windll.shell32.IsUserAnAdmin()
-- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get return is_admin
-- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role
#----------------------------------------------------------
create or alter mapping win_admins1 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_junior.name};
commit; @pytest.mark.version('>=4.0')
create view v_info as @pytest.mark.platform('Windows')
select a.mon$user, a.mon$role, a.mon$remote_protocol, a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys):
;
grant select on v_info to public; if not is_admin():
commit; pytest.skip("Current OS user must have admin rights.")
"""
act.isql(switches=['-q'], input = sql_init) sql_init = f"""
assert act.clean_stdout == '' set bail on;
act.reset() create table test(id int);
grant select on test to role {tmp_role_senior.name};
sql_check = f""" commit;
-- This will make connection with tole = {tmp_role_junior.name}
connect '{THIS_COMPUTER_NAME}:{act.db.db_path}'; -- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get
-- Statement failed, SQLSTATE = 28000 /Missing security context for <test_database>
set list on; -- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB:
select 'point-1' as msg, v.* from v_info v; create or alter mapping trusted_auth using plugin win_sspi from any user to user;
commit;
-- MUST FAIL because neither user nor its role has no access rights to the 'TEST' table: -- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get
select count(*) as test_rows from test; -- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role
commit;
create or alter mapping win_admins1 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_junior.name};
-- Make temporary connection as SYSDBA and change mapping from predefined_group domain_any_rid_admins
-- so that any connection can get {tmp_role_senior.name} role as trusted role: create view v_info as
connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; select a.mon$user, a.mon$role, a.mon$remote_protocol, a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection
;
drop mapping win_admins1; grant select on v_info to public;
grant {tmp_role_junior.name} to public; commit;
"""
-- Following statement means that any attachment will be granted with role <tmp_role_senior>
-- which, in turn was granted for SELECT from table 'test': act.isql(switches=['-q'], input = sql_init, combine_output = True)
create or alter mapping win_admins2 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_senior.name}; assert act.clean_stdout == ''
commit; act.reset()
connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role_junior.name.upper()}; sql_check = f"""
-- DO NOT add 'set bail' here!
select 'point-2' as msg, v.* from v_info v; -- This will make connection with tole = {tmp_role_junior.name}
connect '{THIS_COMPUTER_NAME}:{act.db.db_path}';
set term ^;
execute block as set list on;
begin select 'point-1' as msg, v.* from v_info v;
-- Following statement:
-- 1) must pass without any error; -- MUST FAIL because neither user nor its role has no access rights to the 'TEST' table:
-- 2) leads to change effective role from {tmp_role_junior.name} to {tmp_role_senior.name}: select count(*) as test_rows from test;
set trusted role; commit;
end
^ -- Make temporary connection as SYSDBA and change mapping from predefined_group domain_any_rid_admins
set term ;^ -- so that any connection can get {tmp_role_senior.name} role as trusted role:
commit; connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}';
select 'point-3' as msg, v.* from v_info v; drop mapping win_admins1;
-- this MUST PASS because of trusted role {tmp_role_senior.name} whic has needed access rights: grant {tmp_role_junior.name} to public;
select count(*) as test_rows from test;
commit; -- Following statement means that any attachment will be granted with role <tmp_role_senior>
""" -- which, in turn was granted for SELECT from table 'test':
create or alter mapping win_admins2 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_senior.name};
expected_out = f""" commit;
MSG point-1
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role_junior.name.upper()};
MON$ROLE {tmp_role_junior.name.upper()}
MON$REMOTE_PROTOCOL TCP select 'point-2' as msg, v.* from v_info v;
MON$AUTH_METHOD Mapped from Win_Sspi
Statement failed, SQLSTATE = 28000 set bail on;
no permission for SELECT access to TABLE TEST set term ^;
-Effective user is {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} execute block as
begin
MSG point-2 -- Following statement:
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} -- 1) must pass without any error;
MON$ROLE {tmp_role_junior.name.upper()} -- 2) leads to change effective role from {tmp_role_junior.name} to {tmp_role_senior.name}:
MON$REMOTE_PROTOCOL TCP -- NB: if current OS user has no admin rights then following error will raise at this point:
MON$AUTH_METHOD Mapped from Win_Sspi -- Statement failed, SQLSTATE = 0P000
-- Your attachment has no trusted role
MSG point-3 set trusted role;
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} end
MON$ROLE {tmp_role_senior.name.upper()} ^
MON$REMOTE_PROTOCOL TCP set term ;^
MON$AUTH_METHOD Mapped from Win_Sspi commit;
TEST_ROWS 0 set bail off;
"""
select 'point-3' as msg, v.* from v_info v;
act.expected_stdout = expected_out -- this MUST PASS because of trusted role {tmp_role_senior.name} whic has needed access rights:
act.isql(switches=['-q'], input = sql_check, connect_db=False, credentials = False, combine_output = True) select count(*) as test_rows from test;
assert act.clean_stdout == act.clean_expected_stdout commit;
"""
expected_out = f"""
MSG point-1
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()}
MON$ROLE {tmp_role_junior.name.upper()}
MON$REMOTE_PROTOCOL TCP
MON$AUTH_METHOD Mapped from Win_Sspi
Statement failed, SQLSTATE = 28000
no permission for SELECT access to TABLE TEST
-Effective user is {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()}
MSG point-2
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()}
MON$ROLE {tmp_role_junior.name.upper()}
MON$REMOTE_PROTOCOL TCP
MON$AUTH_METHOD Mapped from Win_Sspi
MSG point-3
MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()}
MON$ROLE {tmp_role_senior.name.upper()}
MON$REMOTE_PROTOCOL TCP
MON$AUTH_METHOD Mapped from Win_Sspi
TEST_ROWS 0
"""
act.expected_stdout = expected_out
act.isql(switches=['-q'], input = sql_check, connect_db=False, credentials = False, combine_output = True)
assert act.clean_stdout == act.clean_expected_stdout