fix: complete durable workspace runtime config handoff
This commit is contained in:
+74
-12
@@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -572,25 +573,80 @@ def _validate_raw_config_shape(raw: dict[str, Any], path: Path) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _read_runtime_fd(fd: int, label: str, expected_mode: int = 0o400) -> tuple[bytes, os.stat_result]:
|
||||
try:
|
||||
info = os.fstat(fd)
|
||||
if (not stat.S_ISREG(info.st_mode) or info.st_nlink != 1
|
||||
or stat.S_IMODE(info.st_mode) != expected_mode
|
||||
or info.st_uid != os.getuid()):
|
||||
raise OSError("unsafe runtime descriptor")
|
||||
os.lseek(fd, 0, os.SEEK_SET)
|
||||
chunks: list[bytes] = []
|
||||
total = 0
|
||||
while chunk := os.read(fd, 1024 * 1024):
|
||||
total += len(chunk)
|
||||
if total > 16 * 1024 * 1024:
|
||||
raise OSError("runtime descriptor too large")
|
||||
chunks.append(chunk)
|
||||
return b"".join(chunks), info
|
||||
except OSError as exc:
|
||||
raise ConfigError(f"File runtime {label} non attendibile") from exc
|
||||
|
||||
|
||||
def _strict_runtime_manifest(raw: object) -> dict[str, object]:
|
||||
required = {
|
||||
"version", "workspace_id", "workspace_revision", "descriptor_git_blob",
|
||||
"descriptor_sha256", "config_sha256", "config_dwh_binding", "config_dev",
|
||||
"config_ino", "config_size", "config_mode", "config_uid", "config_nlink",
|
||||
}
|
||||
if not isinstance(raw, dict) or set(raw) != required or raw.get("version") != 1:
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
if not isinstance(raw.get("config_dwh_binding"), dict):
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
binding = raw["config_dwh_binding"]
|
||||
if set(binding) != {"workspace_id", "config_fingerprint", "input_fingerprint"} or any(not isinstance(v, str) for v in binding.values()):
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
for key in ("descriptor_sha256", "config_sha256"):
|
||||
if not isinstance(raw[key], str) or not re.fullmatch(r"[0-9a-f]{64}", raw[key]):
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
for key in ("config_dev", "config_ino", "config_size", "config_uid", "config_nlink"):
|
||||
if not isinstance(raw[key], str) or not raw[key].isdigit():
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
if raw["config_mode"] != "400":
|
||||
raise ConfigError("Manifest runtime non valido")
|
||||
return raw
|
||||
|
||||
|
||||
def load_config(path: Path) -> Config:
|
||||
# Backend runtime leases pass the verified canonical config as fd 3 while retaining
|
||||
# the ordinary absolute -c argument for diagnostics and source identity. Never reopen
|
||||
# that pathname: an ancestor or leaf replacement after spawn must not alter bytes used
|
||||
# by the harness.
|
||||
runtime_manifest: dict[str, object] | None = None
|
||||
runtime_fd = os.environ.get("THT_CONFIG_FD")
|
||||
if runtime_fd is not None:
|
||||
manifest_fd = os.environ.get("THT_CONFIG_MANIFEST_FD")
|
||||
expected_manifest = os.environ.get("THT_CONFIG_MANIFEST_SHA256")
|
||||
if runtime_fd is not None or manifest_fd is not None or expected_manifest is not None:
|
||||
if runtime_fd is None or manifest_fd is None or expected_manifest is None or not re.fullmatch(r"[0-9a-f]{64}", expected_manifest):
|
||||
raise ConfigError("Handoff runtime incompleto")
|
||||
try:
|
||||
fd = int(runtime_fd)
|
||||
info = os.fstat(fd)
|
||||
if (not stat.S_ISREG(info.st_mode) or info.st_nlink != 1
|
||||
or stat.S_IMODE(info.st_mode) != 0o400
|
||||
or info.st_uid != os.getuid()):
|
||||
raise OSError("unsafe runtime config descriptor")
|
||||
chunks: list[bytes] = []
|
||||
while chunk := os.read(fd, 1024 * 1024):
|
||||
chunks.append(chunk)
|
||||
source_text = b"".join(chunks).decode("utf-8")
|
||||
except (OSError, UnicodeError, ValueError) as exc:
|
||||
config_bytes, config_info = _read_runtime_fd(int(runtime_fd), "config")
|
||||
manifest_bytes, manifest_info = _read_runtime_fd(int(manifest_fd), "manifest", 0o600)
|
||||
if hashlib.sha256(manifest_bytes).hexdigest() != expected_manifest:
|
||||
raise ConfigError("Manifest runtime modificato")
|
||||
runtime_manifest = _strict_runtime_manifest(json.loads(manifest_bytes.decode("utf-8")))
|
||||
if (runtime_manifest["config_sha256"] != hashlib.sha256(config_bytes).hexdigest()
|
||||
or int(runtime_manifest["config_dev"]) != config_info.st_dev
|
||||
or int(runtime_manifest["config_ino"]) != config_info.st_ino
|
||||
or int(runtime_manifest["config_size"]) != config_info.st_size
|
||||
or int(runtime_manifest["config_uid"]) != config_info.st_uid
|
||||
or int(runtime_manifest["config_nlink"]) != config_info.st_nlink
|
||||
or config_info.st_dev == manifest_info.st_dev and config_info.st_ino == manifest_info.st_ino):
|
||||
raise ConfigError("Identità config runtime non valida")
|
||||
source_text = config_bytes.decode("utf-8")
|
||||
except (OSError, UnicodeError, ValueError, json.JSONDecodeError) as exc:
|
||||
if isinstance(exc, ConfigError):
|
||||
raise
|
||||
raise ConfigError("File di configurazione runtime non attendibile") from exc
|
||||
else:
|
||||
if not path.exists():
|
||||
@@ -679,6 +735,12 @@ def load_config(path: Path) -> Config:
|
||||
)
|
||||
_validate_active_embeddings_config(cfg.embeddings, path)
|
||||
_validate_active_vector_config(cfg.vectors, path)
|
||||
if runtime_manifest is not None:
|
||||
from tht.jobs.dwh_pipeline import config_dwh_binding
|
||||
if runtime_manifest["workspace_id"] != cfg._workspace_id or runtime_manifest["workspace_revision"] != cfg._workspace_revision:
|
||||
raise ConfigError("Identità workspace runtime non valida")
|
||||
if config_dwh_binding(cfg) != runtime_manifest["config_dwh_binding"]:
|
||||
raise ConfigError("Binding DWH runtime modificato")
|
||||
return cfg
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user