from __future__ import annotations from pathlib import Path from tempfile import TemporaryDirectory from typing import Any, Dict, List from lab.compose import compose_payload from lab.config import ENV_CATALOG_DIR, REPRO_MAP_PATH, REPRO_PROFILES_DIR from lab.utils import command_available, read_yaml, run, write_yaml def validate_assets() -> List[str]: errors: List[str] = [] if not REPRO_MAP_PATH.exists(): errors.append(f"missing repro map: {REPRO_MAP_PATH}") if not ENV_CATALOG_DIR.exists(): errors.append(f"missing environment catalog dir: {ENV_CATALOG_DIR}") for path in sorted(REPRO_PROFILES_DIR.rglob("*.yaml")): content = read_yaml(path, default=None) if not isinstance(content, dict): errors.append(f"invalid repro profile yaml: {path}") continue for field in [ "profile_id", "match_rules", "vuln_family", "provisioning_mode", "attack_actions", "baseline_actions", "success_criteria", "cleanup_policy", "destructive_risk", "allowed_target_types", ]: if field not in content: errors.append(f"repro profile missing {field}: {path}") fixture_path = content.get("fixture_path") if fixture_path and not Path(fixture_path).exists(): errors.append(f"fixture path missing for {path}: {fixture_path}") docker_available = command_available("docker") profile_roots = sorted((ENV_CATALOG_DIR.parent.parent / "profiles").rglob("*.yaml")) for path in profile_roots: content = read_yaml(path, default=None) if not isinstance(content, dict): errors.append(f"invalid environment profile yaml: {path}") continue for field in ["profile_id", "system_id", "services", "cleanup_policy"]: if field not in content: errors.append(f"environment profile missing {field}: {path}") if docker_available: with TemporaryDirectory() as temp_dir: compose_path = Path(temp_dir) / "compose.yaml" write_yaml(compose_path, compose_payload(content)) result = run(["docker", "compose", "-f", str(compose_path), "config"], cwd=compose_path.parent) if result.returncode != 0: errors.append(f"docker compose config failed for {path}: {result.stderr.strip() or result.stdout.strip()}") return errors