mirror of
https://github.com/Av0idD4rk/firegex.git
synced 2026-10-23 21:42:05 +00:00
81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
"""Tests that restart the instance they are testing.
|
|
|
|
Some settings are read **once**, at process startup — the IP allowlist, the proxy header
|
|
it trusts, whether authentication is asked for at boot — so there is no way to exercise
|
|
them against a running instance. These drive `run.py stop`/`start` themselves for each
|
|
scenario, which is why they are not collected by default (`pytest.ini`'s `testpaths` does
|
|
not include this directory) and have to be asked for by name:
|
|
|
|
pytest standalone
|
|
|
|
Expect them to bounce whatever firegex you have running, and to leave an unrestricted one
|
|
behind at the end. They have to run on the same host firegex runs on, with whatever
|
|
`run.py` itself needs.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import time
|
|
|
|
import pytest
|
|
import requests
|
|
|
|
REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
BASE = "http://127.0.0.1:4444/"
|
|
PASSWORD = "testpassword"
|
|
|
|
|
|
def run_py(*args, timeout=180) -> int:
|
|
return subprocess.run(["python3", "run.py", *args], cwd=REPO_ROOT,
|
|
timeout=timeout).returncode
|
|
|
|
|
|
def wait_ready(timeout: float = 90) -> bool:
|
|
"""A 403 counts as ready: it means the app answered, unlike a connection error.
|
|
|
|
`/api/status` is the endpoint being probed, and under a restrictive allowlist the
|
|
correct answer to it *is* a refusal.
|
|
"""
|
|
deadline = time.time() + timeout
|
|
while time.time() < deadline:
|
|
try:
|
|
if requests.get(BASE + "api/status", timeout=2).status_code in (200, 403):
|
|
return True
|
|
except requests.RequestException:
|
|
pass
|
|
time.sleep(1)
|
|
return False
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def restart():
|
|
"""Bring firegex up with a given configuration, and leave an unrestricted one behind.
|
|
|
|
The cleanup is not tidiness: every other test module in this suite assumes it can
|
|
reach the instance from loopback with a password, and a run that stopped halfway
|
|
through a restrictive scenario would break all of them.
|
|
"""
|
|
def _restart(allowed_ips=None, proxy_ip_header=None, unsafe_disable_auth=None):
|
|
run_py("stop")
|
|
args = ["start", "-P", PASSWORD]
|
|
# An empty string still has to be passed explicitly, to clear a previous value.
|
|
if allowed_ips is not None:
|
|
args += ["--allowed-ips", allowed_ips]
|
|
if proxy_ip_header is not None:
|
|
args += ["--proxy-ip-header", proxy_ip_header]
|
|
if unsafe_disable_auth is not None:
|
|
args += ["--unsafe-disable-auth" if unsafe_disable_auth
|
|
else "--no-unsafe-disable-auth"]
|
|
run_py(*args)
|
|
assert wait_ready(), "firegex did not come back up after the restart"
|
|
|
|
yield _restart
|
|
|
|
_restart(allowed_ips="", unsafe_disable_auth=False)
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def only_on_the_host_that_runs_it():
|
|
if not os.path.isfile(os.path.join(REPO_ROOT, "run.py")):
|
|
pytest.skip("these have to run from a clone, on the host firegex runs on")
|