diff --git a/.coveragerc b/.coveragerc index 458f36c16..96e20a217 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,9 +1,9 @@ [run] branch = True -include = - pyrdp/* - twisted/* - bin/* +source = + pyrdp + twisted + bin [report] # Regexes for lines to exclude from consideration diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d83c4e431..130f3e7f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,11 +43,26 @@ jobs: - name: Install ci dependencies run: pip install -r requirements-ci.txt + - name: Extract test files + uses: DuckSoft/extract-7z-action@v1.0 + with: + pathSource: test/files/test_files.zip + pathTarget: test/files + - name: Integration Test with a prerecorded PCAP. working-directory: ./ - run: coverage run test/test.py + run: coverage run test/test_prerecorded.py + + - name: pyrdp-mitm.py initialization integration test + working-directory: ./ + run: coverage run --append test/test_mitm_initialization.py dummy_value + + - name: pyrdp-player.py read a replay in headless mode test + working-directory: ./ + run: coverage run --append bin/pyrdp-player.py --headless test/files/test_session.replay - name: Coverage + working-directory: ./ run: coverage report --fail-under=40 @@ -70,6 +85,20 @@ jobs: working-directory: . run: pip install -U -e . + - name: Extract test files + uses: DuckSoft/extract-7z-action@v1.0 + with: + pathSource: test/files/test_files.zip + pathTarget: test/files + - name: Integration Test with a prerecorded PCAP. working-directory: ./ - run: python test/test.py + run: python test/test_prerecorded.py + + - name: pyrdp-mitm.py initialization test + working-directory: ./ + run: bin/pyrdp-mitm.py --test localhost + + - name: pyrdp-player.py read a replay in headless mode test + working-directory: ./ + run: bin/pyrdp-player.py --headless test/files/test_session.replay diff --git a/bin/pyrdp-mitm.py b/bin/pyrdp-mitm.py index 427329513..a48d6e3ed 100755 --- a/bin/pyrdp-mitm.py +++ b/bin/pyrdp-mitm.py @@ -10,12 +10,11 @@ # Need to install this reactor before importing other twisted code from twisted.internet import asyncioreactor + asyncioreactor.install(asyncio.get_event_loop()) from twisted.internet import reactor -from pyrdp.core import settings from pyrdp.core.mitm import MITMServerFactory -from pyrdp.mitm import MITMConfig, DEFAULTS from pyrdp.mitm.cli import showConfiguration, configure from pyrdp.logging import LOGGER_NAMES diff --git a/pyrdp/mitm/cli.py b/pyrdp/mitm/cli.py index 464e8f00a..3de0a2f8f 100644 --- a/pyrdp/mitm/cli.py +++ b/pyrdp/mitm/cli.py @@ -13,16 +13,16 @@ import logging.handlers import os import sys -from typing import Tuple -from pathlib import Path from base64 import b64encode +from pathlib import Path +from typing import Tuple import OpenSSL -from pyrdp.core.ssl import ServerTLSContext from pyrdp.core import settings -from pyrdp.logging import LOGGER_NAMES, configure as configureLoggers -from pyrdp.mitm.config import MITMConfig, DEFAULTS +from pyrdp.core.ssl import ServerTLSContext +from pyrdp.logging import configure as configureLoggers, LOGGER_NAMES +from pyrdp.mitm.config import DEFAULTS, MITMConfig def parseTarget(target: str) -> Tuple[str, int]: @@ -203,12 +203,12 @@ def configure(cmdline=None) -> MITMConfig: if args.log_level: cfg.set('vars', 'level', args.log_level) - configureLoggers(cfg) - logger = logging.getLogger(LOGGER_NAMES.PYRDP) - outDir = Path(cfg.get('vars', 'output_dir')) outDir.mkdir(exist_ok=True) + configureLoggers(cfg) + logger = logging.getLogger(LOGGER_NAMES.PYRDP) + targetHost, targetPort = parseTarget(args.target) key, certificate = validateKeyAndCertificate(args.private_key, args.certificate) diff --git a/test/files/test_files.zip b/test/files/test_files.zip new file mode 100644 index 000000000..f32c654a9 Binary files /dev/null and b/test/files/test_files.zip differ diff --git a/test/files/test_session.zip b/test/files/test_session.zip deleted file mode 100644 index 04467218e..000000000 Binary files a/test/files/test_session.zip and /dev/null differ diff --git a/test/test_mitm_initialization.py b/test/test_mitm_initialization.py new file mode 100644 index 000000000..573fe46db --- /dev/null +++ b/test/test_mitm_initialization.py @@ -0,0 +1,21 @@ +#!/usr/bin/python3 + +# +# This file is part of the PyRDP project. +# Copyright (C) 2020 GoSecure Inc. +# Licensed under the GPLv3 or later. +# + +""" +Integration test for the initialization of pyrdp-mitm.py. +It could be enhanced with relevant assertions but for now only executes the code to catch +potential basic errors/import problems. +""" +from pyrdp.core.mitm import MITMServerFactory +from pyrdp.mitm.cli import configure + + +if __name__ == "__main__": + config = configure() + server_factory = MITMServerFactory(config) + server_factory.buildProtocol(addr=None) diff --git a/test/test.py b/test/test_prerecorded.py similarity index 97% rename from test/test.py rename to test/test_prerecorded.py index 6969b2e36..a0e745aed 100644 --- a/test/test.py +++ b/test/test_prerecorded.py @@ -6,7 +6,6 @@ # Licensed under the GPLv3 or later. # import logging -import zipfile from pathlib import Path from scapy.all import packet, rdpcap @@ -181,7 +180,6 @@ def buildDeviceChannel(self, client, server): def main(): - input_path = "test/files/test_session.zip" pcap_path = "test/files/test_session.pcap" client_ip = "192.168.38.1" mitm_ip = "192.168.38.1" @@ -191,10 +189,6 @@ def main(): logging.basicConfig(level=logging.CRITICAL) logging.getLogger("scapy").setLevel(logging.ERROR) - # Unzip the pcap - with zipfile.ZipFile(input_path, 'r') as zip_ref: - zip_ref.extractall("test/files") - packets = rdpcap(pcap_path) test_mitm = TestMITM(output_path)