"""rustdesk-server — identity-key round-trip across three independent surfaces (§4.3-style). hbbs mints an ed25519 identity keypair on first boot into the shared rustdesk_data volume; the PUBLIC key is what clients configure to pin the server. This is the recipe's defining generated state, and we read it back through three genuinely different paths: 1. HTTPS through Traefik + the cc-ci status sidecar: GET /id_ed25519.pub (the serving path a remote client could observe), 2. hbbs's OWN startup telemetry: the `Key: ` log line (docker service logs), 3. the volume file itself, read inside the status sidecar (cat /pub/id_ed25519.pub). All three must AGREE and be a valid base64-encoded 32-byte ed25519 public key. A wedged or crash-looping hbbs fails (1) with 404 forever (no key file); a key mismatch across surfaces would mean we are reading different deployments' state — either way this test names the broken layer. Non-vacuous: every surface carries app-generated state, nothing is echoed from config. """ from __future__ import annotations import base64 import os import re import subprocess import sys import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner")) from harness import lifecycle # noqa: E402 _KEY_RE = re.compile(rb"Key: ([A-Za-z0-9+/]{43}=)") def _stack(domain: str) -> str: return domain.replace(".", "_") def _https_key(domain: str) -> tuple[int, str]: return lifecycle.http_fetch(domain, "/id_ed25519.pub") def _log_key(domain: str) -> bytes | None: out = subprocess.run( ["docker", "service", "logs", "--tail", "200", f"{_stack(domain)}_app"], capture_output=True, text=True, timeout=60, ).stdout m = _KEY_RE.search(out.encode()) return m.group(1) if m else None def _volume_key(domain: str) -> str: return lifecycle.exec_in_app(domain, ["cat", "/pub/id_ed25519.pub"], service="status").strip() def test_identity_key_agrees_across_https_log_and_volume(live_app): https_status, https_body = _https_key(live_app) assert https_status == 200, ( f"status route /id_ed25519.pub not serving (HTTP {https_status}) — hbbs never minted " "its key, or the status sidecar/routing is broken" ) https_key = https_body.strip().encode() log_key = _log_key(live_app) assert log_key is not None, "hbbs startup log carries no 'Key: ' line (telemetry)" vol_key = _volume_key(live_app).encode() assert https_key == log_key == vol_key, ( "identity key disagrees across surfaces — " f"https={https_key[:20]!r} log={log_key[:20]!r} volume={vol_key[:20]!r} " "(reading different deployments' state?)" ) raw = base64.b64decode(https_key, validate=True) assert len(raw) == 32, f"not a 32-byte ed25519 public key ({len(raw)} bytes)" @pytest.mark.parametrize( "path", [ "/", "/id_ed25519", # the PRIVATE key lives in the same volume — must never be served "/db_v2.sqlite3", "/db_v2.sqlite3-wal", ], ) def test_status_route_serves_only_the_public_key(live_app, path): """Anything but the exact .pub location 404s (default surface = deny). The private key and the sqlite peer DB share the status sidecar's volume — a 200 on any of these paths would be a real exposure.""" status, _ = lifecycle.http_fetch(live_app, path) assert status == 404, f"status route served {path} (HTTP {status}) — exposure, not health"