# SPDX-License-Identifier: AGPL-3.0-or-later """ Verify that the HTTPS Caddyfile template (generated by entrypoint.sh): - Includes `decnet_h3` in the global block when http/3 is selected. - Does NOT include `h3` in the Caddy `protocols` line when http/3 is selected (H3App owns UDP/443 directly). - Does NOT include `decnet_h3` when http/3 is not selected. """ from __future__ import annotations import subprocess import tempfile import os from pathlib import Path import pytest ENTRYPOINT = Path(__file__).parent.parent.parent / "decnet" / "templates" / "https" / "entrypoint.sh" def run_entrypoint_to_caddyfile(http_versions: list[str], env_extra: dict | None = None) -> str: """ Run entrypoint.sh with a stub TLS cert and extract the generated Caddyfile. Returns the Caddyfile content as a string, or raises on failure. """ if not ENTRYPOINT.exists(): pytest.skip("entrypoint.sh not found") with tempfile.TemporaryDirectory() as tmpdir: # Generate a throwaway self-signed cert so entrypoint doesn't fail. cert_path = os.path.join(tmpdir, "cert.pem") key_path = os.path.join(tmpdir, "key.pem") subprocess.run( ["openssl", "req", "-x509", "-newkey", "rsa:2048", "-nodes", "-keyout", key_path, "-out", cert_path, "-days", "1", "-subj", "/CN=test"], capture_output=True, check=True, ) caddy_dir = os.path.join(tmpdir, "caddy") os.makedirs(caddy_dir, exist_ok=True) caddyfile_path = os.path.join(caddy_dir, "Caddyfile") env = { "PATH": os.environ.get("PATH", "/usr/bin:/bin"), "HTTP_VERSIONS": str(http_versions).replace("'", '"'), "TLS_DIR": tmpdir, "TLS_CERT": cert_path, "TLS_KEY": key_path, "NODE_NAME": "test", "LOG_TARGET": "", "DECNET_FP_SOCK": os.path.join(tmpdir, "fp.sock"), } if env_extra: env.update(env_extra) # Patch entrypoint to stop after writing the Caddyfile (before Flask). script = f""" set -e export TLS_DIR="{tmpdir}" export TLS_CERT="{cert_path}" export TLS_KEY="{key_path}" """ # Source just the variable-computation part of entrypoint.sh then write # the Caddyfile. We replace `exec caddy` with `exit 0`. src = ENTRYPOINT.read_text() # Replace the Flask+Caddy run portion with early exit. src = src.replace("python3 /opt/server.py &", "exit 0") patched = script + src import json http_versions_json = json.dumps(http_versions) env["HTTP_VERSIONS"] = http_versions_json result = subprocess.run( ["bash", "-c", patched], env=env, capture_output=True, text=True, timeout=10, ) caddyfile_content = "" # The Caddyfile is written to /etc/caddy/Caddyfile. # Since we're not root in tests, override it via env trick — just # extract the content from the script output/error instead. # Better: redirect output of the heredoc. # Actually: just parse the script to extract the heredoc. import re m = re.search(r"cat > /etc/caddy/Caddyfile <