2021-04-26 20:07:00 +02:00
|
|
|
#coding:utf-8
|
2022-01-26 21:10:46 +01:00
|
|
|
|
|
|
|
"""
|
|
|
|
ID: issue-6321
|
|
|
|
ISSUE: 6321
|
|
|
|
TITLE: Restore of encrypted backup of database with SQL dialect 1 fails
|
|
|
|
DESCRIPTION:
|
2022-06-15 20:36:51 +02:00
|
|
|
Database is created in dialect 3, then encrypted and after this we apply 'gfix -sql_dialect 1' to it.
|
|
|
|
Then we restore database and validate it.
|
2022-01-26 21:10:46 +01:00
|
|
|
|
|
|
|
Confirmed bug on 4.0.0.1485 (build date: 11-apr-2019), got error on restore:
|
|
|
|
SQL error code = -817
|
|
|
|
Metadata update statement is not allowed by the current database SQL dialect 1
|
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
JIRA: CORE-6071
|
|
|
|
FBTEST: bugs.core_6071
|
|
|
|
NOTES:
|
|
|
|
[15.06.2022] pzotov
|
|
|
|
There is some bug on LINUX with gbak when we have to make backup/restore ENCRYPTED database:
|
|
|
|
1. If we use names of encryption plugin and keyholder WITHOUT quotes (i.e. ENCRYPTION_PLUGIN = 'fbSampleDbCrypt' and ENCRYPTION_HOLDER = 'fbSampleKeyHolder')
|
|
|
|
then backup works fine but *restore* fails with following message:
|
|
|
|
> act.gbak(switches=['-c', '-KEYHOLDER', ENCRYPTION_HOLDER, str(tmp_fbk), str(tmp_res) ])
|
2022-01-26 21:10:46 +01:00
|
|
|
gbak: ERROR:unsuccessful metadata update
|
|
|
|
gbak: ERROR: ALTER DATABASE failed
|
2022-06-15 20:36:51 +02:00
|
|
|
gbak: ERROR: Crypt plugin FBSAMPLEDBCRYPT failed to load
|
2022-01-26 21:10:46 +01:00
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
2. If we enclose names into double quotes then *backup* fails like this:
|
|
|
|
> act.gbak(switches=['-b', '-KEYHOLDER', '"'+ENCRYPTION_HOLDER+'"', '-crypt', '"'+ENCRYPTION_PLUGIN+'"', str(act.db.dsn), str(tmp_fbk)])
|
|
|
|
gbak: ERROR:Key holder plugin "fbSampleKeyHolder" failed to load
|
|
|
|
gbak:Exiting before completion due to errors
|
|
|
|
|
|
|
|
Until this weird error will be fixed, this test must be run only on WINDOWS.
|
|
|
|
Checked on 4.0.1.2692, 5.0.0.509.
|
2022-01-26 21:10:46 +01:00
|
|
|
"""
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
import re
|
|
|
|
import datetime as py_dt
|
|
|
|
from datetime import timedelta
|
|
|
|
import time
|
|
|
|
|
2021-04-26 20:07:00 +02:00
|
|
|
import pytest
|
2022-01-26 21:10:46 +01:00
|
|
|
from firebird.qa import *
|
2022-06-15 20:36:51 +02:00
|
|
|
from firebird.driver import DatabaseError
|
|
|
|
from pathlib import Path
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-01-26 21:10:46 +01:00
|
|
|
db = db_factory()
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
#act = python_act('db', substitutions=[('\\d+ BYTES WRITTEN', '')])
|
|
|
|
act = python_act('db')
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
tmp_fbk = temp_file( filename = 'tmp_core_6071_encrypted.fbk')
|
|
|
|
tmp_res = temp_file( filename = 'tmp_core_6071_restored.fdb')
|
|
|
|
tmp_log = temp_file( filename = 'tmp_core_6071_bkup_rest.log')
|
|
|
|
|
|
|
|
MAX_ENCRYPT_DECRYPT_MS = 5000
|
|
|
|
ENCRYPTION_PLUGIN = 'fbSampleDbCrypt'
|
|
|
|
ENCRYPTION_HOLDER = 'fbSampleKeyHolder'
|
|
|
|
ENCRYPTION_KEY = 'Red'
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-06-15 20:36:51 +02:00
|
|
|
@pytest.mark.encryption
|
2022-01-26 21:10:46 +01:00
|
|
|
@pytest.mark.version('>=4.0')
|
|
|
|
@pytest.mark.platform('Windows')
|
2022-06-15 20:36:51 +02:00
|
|
|
def test_1(act: Action, tmp_fbk: Path, tmp_res: Path, tmp_log: Path, capsys):
|
|
|
|
encryption_started = False
|
|
|
|
encryption_finished = False
|
|
|
|
with act.db.connect() as con:
|
|
|
|
|
|
|
|
t1=py_dt.datetime.now()
|
|
|
|
d1 = t1-t1
|
|
|
|
sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}" key "{ENCRYPTION_KEY}"'
|
|
|
|
try:
|
|
|
|
con.execute_immediate(sttm)
|
|
|
|
con.commit()
|
|
|
|
encryption_started = True
|
|
|
|
except DatabaseError as e:
|
|
|
|
# -ALTER DATABASE failed
|
|
|
|
# -Crypt plugin fbSampleDbCrypt failed to load
|
|
|
|
# ==> no sense to do anything else, encryption_started remains False.
|
|
|
|
print( e.__str__() )
|
|
|
|
|
|
|
|
while encryption_started:
|
|
|
|
t2=py_dt.datetime.now()
|
|
|
|
d1=t2-t1
|
|
|
|
if d1.seconds*1000 + d1.microseconds//1000 > MAX_ENCRYPT_DECRYPT_MS:
|
|
|
|
print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {MAX_ENCRYPT_DECRYPT_MS} ms.')
|
|
|
|
break
|
|
|
|
|
|
|
|
# Possible output:
|
|
|
|
# Database not encrypted
|
|
|
|
# Database encrypted, crypt thread not complete
|
|
|
|
act.isql(switches=['-q'], input = 'show database;', combine_output = True)
|
|
|
|
if 'Database encrypted' in act.stdout:
|
|
|
|
if 'not complete' in act.stdout:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
encryption_finished = True
|
|
|
|
break
|
|
|
|
act.reset()
|
|
|
|
|
|
|
|
if encryption_finished:
|
|
|
|
act.expected_stdout = ''
|
|
|
|
act.expected_stderr = ''
|
|
|
|
|
|
|
|
# All following command must NOT issue anything.
|
|
|
|
# Any output must be considered as errror:
|
|
|
|
#
|
|
|
|
act.gfix(switches=['-sql_dialect', '1', act.db.dsn])
|
|
|
|
act.gbak(switches=['-b', '-KEYHOLDER', ENCRYPTION_HOLDER, '-crypt', ENCRYPTION_PLUGIN, str(act.db.dsn), str(tmp_fbk)])
|
|
|
|
act.gbak(switches=['-c', '-KEYHOLDER', ENCRYPTION_HOLDER, str(tmp_fbk), str(tmp_res) ])
|
|
|
|
act.gfix(switches=['-v', '-full', tmp_res])
|