mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-23 05:53:06 +01:00
155 lines
5.1 KiB
Python
155 lines
5.1 KiB
Python
#coding:utf-8
|
|
|
|
"""
|
|
ID: syspriv.use-gbak-utility
|
|
TITLE: Check ability to to make database backup
|
|
DESCRIPTION:
|
|
FBTEST: functional.syspriv.use_gbak_utility
|
|
NOTES:
|
|
[23.05.2022] pzotov
|
|
Checked on 4.0.1.2692, 5.0.0.497.
|
|
"""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
from firebird.qa import *
|
|
from firebird.driver.types import DatabaseError, SrvBackupFlag, SrvRestoreFlag
|
|
|
|
substitutions = [('[ \t]+', ' '), ('ATT_NAME .*TEST.FDB', 'ATT_NAME TEST.FDB'), ('TCPv(4|6){1}', 'TCP')]
|
|
|
|
db = db_factory()
|
|
|
|
db_temp = db_factory(filename = 'tmp_use_gbak.fdb.tmp')
|
|
fbk_tmp1 = temp_file('tmp_backup_via_services_api.fbk.tmp')
|
|
fbk_tmp2 = temp_file('tmp_backup_via_gbak_utility.fbk.tmp')
|
|
fdb_temp = temp_file('tmp_restored.fdb.tmp')
|
|
|
|
tmp_user = user_factory('db', name='tmp_syspriv_user', password='123')
|
|
tmp_role = role_factory('db', name='tmp_role_for_use_gbak_utility')
|
|
|
|
act = python_act('db', substitutions=substitutions)
|
|
|
|
expected_stdout_gbak = """
|
|
Use Services API. Backup as NON-DBA user completed OK.
|
|
Use gbak utility. Backup as NON-DBA user completed OK.
|
|
|
|
"""
|
|
|
|
expected_stdout_isql="""
|
|
ATT_NAME TEST.FDB
|
|
ATT_USER TMP_SYSPRIV_USER
|
|
ATT_ROLE TMP_ROLE_FOR_USE_GBAK_UTILITY
|
|
ATT_PROT TCP
|
|
SYS_PRIV_MASK 0008010000000000
|
|
|
|
ATT_NAME TEST.FDB
|
|
ATT_USER TMP_SYSPRIV_USER
|
|
ATT_ROLE TMP_ROLE_FOR_USE_GBAK_UTILITY
|
|
ATT_PROT TCP
|
|
SYS_PRIV_MASK 0008010000000000
|
|
|
|
Records affected: 2
|
|
"""
|
|
|
|
@pytest.mark.version('>=4.0')
|
|
def test_1(act: Action, tmp_user: User, tmp_role:Role, fbk_tmp1: Path, fbk_tmp2: Path, fdb_temp: Path, capsys):
|
|
|
|
init_script = f"""
|
|
set wng off;
|
|
set bail on;
|
|
set list on;
|
|
set count on;
|
|
|
|
create or alter view v_check as
|
|
select
|
|
upper(mon$database_name) as db_name
|
|
,current_user as who_ami
|
|
,r.rdb$role_name as sys_role_name
|
|
,rdb$role_in_use(r.rdb$role_name) as rdb_role_in_use
|
|
,r.rdb$system_privileges as sys_priv_mask
|
|
from mon$database m cross join rdb$roles r;
|
|
commit;
|
|
|
|
alter user {tmp_user.name} password '123' revoke admin role;
|
|
revoke all on all from {tmp_user.name};
|
|
commit;
|
|
|
|
recreate table test(x int, b blob);
|
|
commit;
|
|
|
|
insert into test values(1, upper('qwertyuioplkjhgfdsazxcvbnm') );
|
|
commit;
|
|
|
|
recreate table att_log (
|
|
att_id int,
|
|
att_name varchar(255),
|
|
att_user varchar(255),
|
|
att_role varchar(255),
|
|
att_prot varchar(255),
|
|
sys_priv_mask rdb$system_privileges -- binary(8) nullable
|
|
);
|
|
|
|
commit;
|
|
|
|
grant select on v_check to public;
|
|
grant all on att_log to public;
|
|
-- [ !! ] do NOT: grant select on test to {tmp_user.name}; -- [ !! ]
|
|
commit;
|
|
|
|
set term ^;
|
|
create or alter trigger trg_connect active on connect as
|
|
begin
|
|
if ( upper(current_user) <> upper('SYSDBA') ) then
|
|
in autonomous transaction do
|
|
insert into att_log(att_id, att_name, att_user, att_role, att_prot, sys_priv_mask)
|
|
select
|
|
a.mon$attachment_id
|
|
,upper(a.mon$attachment_name)
|
|
,a.mon$user
|
|
,v.sys_role_name
|
|
,a.mon$remote_protocol
|
|
,v.sys_priv_mask
|
|
from mon$attachments a
|
|
join v_check v on v.rdb_role_in_use is true
|
|
where a.mon$user = current_user
|
|
;
|
|
|
|
end
|
|
^
|
|
set term ;^
|
|
commit;
|
|
|
|
-- Ability to make database backup.
|
|
-- NB: SELECT_ANY_OBJECT_IN_DATABASE - mandatory for reading data from tables et al.
|
|
alter role {tmp_role.name}
|
|
set system privileges to USE_GBAK_UTILITY, SELECT_ANY_OBJECT_IN_DATABASE;
|
|
commit;
|
|
grant default {tmp_role.name} to user {tmp_user.name};
|
|
commit;
|
|
|
|
"""
|
|
act.isql(switches=['-q'], input=init_script)
|
|
|
|
with act.connect_server(user = tmp_user.name, password = tmp_user.password) as srv_nondba:
|
|
try:
|
|
srv_nondba.database.backup( database=act.db.db_path, backup=fbk_tmp1, callback=act.print_callback )
|
|
print('Use Services API. Backup as NON-DBA user completed OK.')
|
|
except DatabaseError as e:
|
|
print(e.__str__())
|
|
|
|
try:
|
|
act.gbak(switches=['-b', '-se', 'localhost:service_mgr', '-user', tmp_user.name, '-password', tmp_user.password, act.db.db_path, fbk_tmp2], combine_output = True )
|
|
print('Use gbak utility. Backup as NON-DBA user completed OK.')
|
|
except DatabaseError as e:
|
|
print(e.__str__())
|
|
|
|
act.stdout = capsys.readouterr().out
|
|
act.expected_stdout = expected_stdout_gbak
|
|
assert act.clean_stdout == act.clean_expected_stdout
|
|
act.reset()
|
|
|
|
# Final check: we must be sure that backup actually was done by NON-dba user rather than 'silently' by SYSDBA:
|
|
act.isql(switches=['-q'], input='set list on; set count on; select att_name, att_user, att_role, att_prot, sys_priv_mask from att_log order by att_id;', connect_db = True, combine_output=True)
|
|
act.expected_stdout = expected_stdout_isql
|
|
assert act.clean_stdout == act.clean_expected_stdout
|