diff --git a/app.py b/app.py index 46a886d..19990a3 100644 --- a/app.py +++ b/app.py @@ -2141,7 +2141,7 @@ def recharge_enrollment_session(session_id: str, additional_devices: int, expire def iso_build_row_to_dict(row) -> dict: (build_id, organization_id, status, output_filename, error_message, - created_at, started_at, finished_at, expires_at) = row + created_at, started_at, finished_at, expires_at, sha256) = row return { "id": str(build_id), "organization_id": str(organization_id), @@ -2152,6 +2152,7 @@ def iso_build_row_to_dict(row) -> dict: "started_at": started_at.isoformat() if started_at else None, "finished_at": finished_at.isoformat() if finished_at else None, "expires_at": expires_at.isoformat() if expires_at else None, + "sha256": sha256, } def fetch_iso_build(build_id: str): @@ -2160,7 +2161,7 @@ def fetch_iso_build(build_id: str): cur.execute( """ SELECT id, organization_id, status, output_filename, error_message, - created_at, started_at, finished_at, expires_at + created_at, started_at, finished_at, expires_at, sha256 FROM iso_builds WHERE id = %s """, @@ -2175,7 +2176,7 @@ def fetch_iso_builds(organization_id: str): cur.execute( """ SELECT id, organization_id, status, output_filename, error_message, - created_at, started_at, finished_at, expires_at + created_at, started_at, finished_at, expires_at, sha256 FROM iso_builds WHERE organization_id = %s ORDER BY created_at DESC @@ -2201,6 +2202,7 @@ def update_iso_build( status: str, output_filename: str | None = None, error_message: str | None = None, + sha256: str | None = None, mark_started: bool = False, mark_finished: bool = False, ): @@ -2217,13 +2219,14 @@ def update_iso_build( UPDATE iso_builds SET status = %s, output_filename = COALESCE(%s, output_filename), - error_message = %s + error_message = %s, + sha256 = COALESCE(%s, sha256) {", started_at = CURRENT_TIMESTAMP" if mark_started else ""} {", finished_at = CURRENT_TIMESTAMP" if mark_finished else ""} {f", expires_at = CURRENT_TIMESTAMP + INTERVAL '{ISO_BUILD_EXPIRY_DAYS} days'" if setzt_expiry else ""} WHERE id = %s """, - (status, output_filename, error_message, build_id), + (status, output_filename, error_message, sha256, build_id), ) def cleanup_old_iso_builds(organization_id: str, keep_build_id) -> None: @@ -2331,6 +2334,20 @@ def compute_iso_volid(organization_name: str) -> str: return f"{sanitized}_{date_suffix}" +def compute_file_sha256(path) -> str: + """ + Streamt die Datei in 1-MB-Bloecken statt sie komplett in den Speicher zu + laden (ISOs sind mehrere GB gross) - laeuft im selben Background-Thread + wie der Bau selbst, blockiert also keinen HTTP-Request. + """ + + hasher = hashlib.sha256() + with open(path, "rb") as f: + for block in iter(lambda: f.read(1024 * 1024), b""): + hasher.update(block) + + return hasher.hexdigest() + def run_iso_build(build_id, organization_id: str, activation_code: str, wifi_ssid: str | None, wifi_psk: str | None) -> None: output_path = ISO_BUILD_OUTPUT_DIR / f"{build_id}.iso" @@ -2371,7 +2388,11 @@ def run_iso_build(build_id, organization_id: str, activation_code: str, wifi_ssi update_iso_build(build_id, status="failed", error_message=error_tail, mark_finished=True) return - update_iso_build(build_id, status="completed", output_filename=output_path.name, mark_finished=True) + sha256 = compute_file_sha256(output_path) + + update_iso_build( + build_id, status="completed", output_filename=output_path.name, sha256=sha256, mark_finished=True + ) cleanup_old_iso_builds(organization_id, build_id) @app.get("/health") diff --git a/migrations/0023_iso_build_sha256.sql b/migrations/0023_iso_build_sha256.sql new file mode 100644 index 0000000..55459a9 --- /dev/null +++ b/migrations/0023_iso_build_sha256.sql @@ -0,0 +1,6 @@ +-- SHA256-Pruefsumme fuer heruntergeladene ISOs (28.08.2026-Fund, Self- +-- Service-Flow-Test): Download laeuft ueber den Kundenplattform-Proxy zu +-- anode, ein Hash zur Integritaetspruefung unabhaengig von diesem Pfad war +-- bislang nicht vorhanden. Einmalig direkt nach erfolgreichem Bau berechnet +-- (nicht bei jedem Seitenaufruf - mehrere GB Datei). +ALTER TABLE iso_builds ADD COLUMN sha256 TEXT;