Files

64 lines
3.1 KiB
Python

import importlib.util
import json
import pathlib
import tarfile
import tempfile
import unittest
from unittest.mock import patch
SCRIPT = pathlib.Path(__file__).resolve().parents[1] / 'tools/q2f-runtime.py'
SPEC = importlib.util.spec_from_file_location('q2f_runtime', SCRIPT)
RUNTIME = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(RUNTIME)
class Q2FRuntimeTests(unittest.TestCase):
def test_exact_cache_is_reused_and_tampering_is_rejected(self):
with tempfile.TemporaryDirectory() as directory:
base = pathlib.Path(directory)
identity = 'overport-test-123456789abc'
payload = base / 'payload'
(payload / 'java/bin').mkdir(parents=True)
for name in ('java/bin/java', 'overportcli.jar', 'overport-installed.json', 'OVR_PORT_LICENSE'):
(payload / name).write_text(name)
files = sorted(p for p in payload.rglob('*') if p.is_file())
sums = ''.join(f'{RUNTIME.digest(p)} {p.relative_to(payload)}\n' for p in files)
(payload / 'VERSION').write_text(identity + '\n')
(payload / 'SHA256SUMS').write_text(sums)
archive = base / f'framely-q2f-{identity}-linux-arm64.tar.gz'
with tarfile.open(archive, 'w:gz') as tar:
tar.add(payload, arcname=f'framely-q2f-{identity}')
descriptor = base / 'requirement.json'
descriptor.write_text(json.dumps({'schemaVersion': 1, 'id': identity,
'archive': archive.name, 'size': archive.stat().st_size,
'sha256': RUNTIME.digest(archive), 'url': 'https://example.invalid/q2f'}))
copies = []
def copy(_requirement, destination):
destination.write_bytes(archive.read_bytes())
copies.append(destination)
with patch.object(RUNTIME, 'download', copy):
cached = RUNTIME.prepare(descriptor, base / 'storage')
self.assertEqual(cached, RUNTIME.prepare(descriptor, base / 'storage'))
self.assertEqual(len(copies), 1)
(cached / 'overportcli.jar').write_text('changed')
with self.assertRaisesRegex(ValueError, 'checksum mismatch'):
RUNTIME.prepare(descriptor, base / 'storage')
def test_archive_rejects_link_and_escape(self):
with tempfile.TemporaryDirectory() as directory:
base = pathlib.Path(directory)
identity = 'overport-test-123456789abc'
archive = base / 'unsafe.tar.gz'
for index, member in enumerate((f'framely-q2f-{identity}/../escape', f'framely-q2f-{identity}/link')):
with tarfile.open(archive, 'w:gz') as tar:
info = tarfile.TarInfo(member)
info.type = tarfile.SYMTYPE if member.endswith('/link') else tarfile.REGTYPE
info.size = 0
tar.addfile(info)
with self.assertRaisesRegex(ValueError, 'Unsafe'):
RUNTIME.extract(archive, base / f'target-{index}', identity)
if __name__ == '__main__':
unittest.main()