feat(golden-images): unauthentifizierte Hosting-Route fuer Golden Images
Analog zur bestehenden /installers/fedora-workstation/ks.cfg-Route:
GET /golden-images/{filename} liefert eine Datei aus data/golden-images/
(Env-Override TUXFLOTTE_GOLDEN_IMAGES_DIR), ohne Auth-Token - das
Zielgeraet hat beim Laden des Golden Image in backend_launch() noch
keins. Kein personalisierter Inhalt (anders als die ISO-Build-Downloads),
deshalb bewusst keine Authentifizierung noetig. Path-Traversal ueber den
Dateinamen wird per Path(...).name-Vergleich abgelehnt (400).
Vorbereitung fuer ADR-0024 Phase 3 (backends/mint-image/backend.sh
GOLDEN_IMAGE_URL zeigt als naechstes hierher).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
e88e0da0da
commit
0acb1b6b81
24
app.py
24
app.py
@ -15,7 +15,7 @@ from uuid import UUID, uuid4
|
||||
import psycopg
|
||||
from psycopg.types.json import Jsonb
|
||||
|
||||
from fastapi import FastAPI, Header, Request
|
||||
from fastapi import FastAPI, Header, HTTPException, Request
|
||||
from pydantic import BaseModel
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
@ -54,6 +54,12 @@ MINT_ISO_PATH = str(Path(os.environ.get("TUXFLOTTE_MINT_ISO_PATH", "data/upstrea
|
||||
# zum Subprocess-cwd (TUXFLOTTE_INSTALLER_DIR) interpretiert, nicht relativ
|
||||
# zum eigenen Arbeitsverzeichnis.
|
||||
ISO_BUILD_OUTPUT_DIR = Path(os.environ.get("TUXFLOTTE_ISO_BUILD_OUTPUT_DIR", "data/iso-builds")).resolve()
|
||||
# Golden Images (ADR-0024): bewusst unauthentifiziert, analog zu
|
||||
# /installers/fedora-workstation/ks.cfg - werden von backend_launch()
|
||||
# per curl geladen, bevor das Zielgeraet irgendein Token besitzt. Kein
|
||||
# personalisierter/kundenspezifischer Inhalt (anders als ISO-Builds oben),
|
||||
# nur ein generisches Basis-Root-Dateisystem pro Distribution.
|
||||
GOLDEN_IMAGES_DIR = Path(os.environ.get("TUXFLOTTE_GOLDEN_IMAGES_DIR", "data/golden-images")).resolve()
|
||||
ISO_BUILD_TIMEOUT_SECONDS = 1800
|
||||
# ISO-Ablauf nach 7 Tagen (Migration 0021): ergaenzt die bestehende
|
||||
# "neuer Build ersetzt alten"-Aufraeumung um eine reine Zeitdimension.
|
||||
@ -2577,6 +2583,22 @@ def get_fedora_kickstart():
|
||||
)
|
||||
|
||||
|
||||
@app.get("/golden-images/{filename}")
|
||||
def get_golden_image(filename: str):
|
||||
# Path-Traversal-Schutz: Path(...).name kappt jeden "../"-Anteil, der
|
||||
# Vergleich mit dem Original-Parameter erkennt den Versuch und lehnt ihn
|
||||
# ab, statt ihn still auf einen anderen Dateinamen umzubiegen.
|
||||
safe_name = Path(filename).name
|
||||
if safe_name != filename:
|
||||
raise HTTPException(status_code=400, detail="invalid_filename")
|
||||
|
||||
file_path = GOLDEN_IMAGES_DIR / safe_name
|
||||
if not file_path.is_file():
|
||||
raise HTTPException(status_code=404, detail="not_found")
|
||||
|
||||
return FileResponse(file_path, media_type="application/zstd")
|
||||
|
||||
|
||||
@app.post("/api/v1/agent/bootstrap")
|
||||
def agent_bootstrap(payload: AgentBootstrapRequest):
|
||||
agent_secret = secrets.token_urlsafe(32)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user