The /opt/emit_capture.py, /opt/syslog_bridge.py, and /usr/libexec/udev/journal-relay files were plaintext and world-readable to any attacker root-shelled into the SSH honeypot — revealing the full capture logic on a single cat. Pack all three into /entrypoint.sh as XOR+gzip+base64 blobs at build time (_build_stealth.py), then decode in-memory at container start and exec the capture loop from a bash -c string. No .py files under /opt, no journal-relay file under /usr/libexec/udev, no argv_zap name anywhere. The LD_PRELOAD shim is installed as /usr/lib/x86_64-linux-gnu/libudev-shared.so.1 — sits next to the real libudev.so.1 and blends into the multiarch layout. A 1-byte random XOR key is chosen at image build so a bare 'base64 -d | gunzip' probe on the visible entrypoint returns binary noise instead of readable Python. Docker-dependent tests live under tests/docker/ behind a new 'docker' pytest marker (excluded from the default run, same pattern as fuzz / live / bench).
36 lines
866 B
Python
36 lines
866 B
Python
"""
|
|
Shared fixtures for tests under `tests/docker/`.
|
|
|
|
All tests here are marked `docker` and excluded from the default run
|
|
(see pyproject.toml addopts). Enable with: `pytest -m docker`.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
|
|
def _docker_available() -> bool:
|
|
if shutil.which("docker") is None:
|
|
return False
|
|
try:
|
|
subprocess.run(
|
|
["docker", "info"],
|
|
check=True,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL,
|
|
timeout=5,
|
|
)
|
|
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, OSError):
|
|
return False
|
|
return True
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def _require_docker():
|
|
if not _docker_available():
|
|
pytest.skip("docker daemon not reachable", allow_module_level=True)
|