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
|
import psycopg
|
||||||
from psycopg.types.json import Jsonb
|
from psycopg.types.json import Jsonb
|
||||||
|
|
||||||
from fastapi import FastAPI, Header, Request
|
from fastapi import FastAPI, Header, HTTPException, Request
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from fastapi.responses import FileResponse
|
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 Subprocess-cwd (TUXFLOTTE_INSTALLER_DIR) interpretiert, nicht relativ
|
||||||
# zum eigenen Arbeitsverzeichnis.
|
# zum eigenen Arbeitsverzeichnis.
|
||||||
ISO_BUILD_OUTPUT_DIR = Path(os.environ.get("TUXFLOTTE_ISO_BUILD_OUTPUT_DIR", "data/iso-builds")).resolve()
|
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_BUILD_TIMEOUT_SECONDS = 1800
|
||||||
# ISO-Ablauf nach 7 Tagen (Migration 0021): ergaenzt die bestehende
|
# ISO-Ablauf nach 7 Tagen (Migration 0021): ergaenzt die bestehende
|
||||||
# "neuer Build ersetzt alten"-Aufraeumung um eine reine Zeitdimension.
|
# "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")
|
@app.post("/api/v1/agent/bootstrap")
|
||||||
def agent_bootstrap(payload: AgentBootstrapRequest):
|
def agent_bootstrap(payload: AgentBootstrapRequest):
|
||||||
agent_secret = secrets.token_urlsafe(32)
|
agent_secret = secrets.token_urlsafe(32)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user