Skip to content

Commit 1110aef

Browse files
authored
Merge pull request #140 from SSobol77/feature/f4-linux-official-evidence-audit-gate
feat: add Linux official evidence audit gate
2 parents cade8bb + fb251d3 commit 1110aef

2 files changed

Lines changed: 132 additions & 0 deletions

File tree

scripts/f4_linter_linux_provisioning.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from __future__ import annotations
2727

28+
import argparse
2829
import importlib
2930
import json
3031
import sys
@@ -122,6 +123,9 @@
122123

123124
LINUX_MANIFEST_SCHEMA_VERSION = 1
124125
LINUX_MANIFEST_FILENAME = "f4-linux-tools.json"
126+
EXIT_OK = 0
127+
EXIT_INVALID = 1
128+
EXIT_OFFICIAL_EVIDENCE_DRIFT = 2
125129

126130
LINUX_PACKAGE_MANAGER_ARTIFACT_IDS: tuple[str, ...] = (
127131
"deb",
@@ -1356,6 +1360,17 @@ def linux_official_distro_evidence_drift_errors() -> list[str]:
13561360
return errors
13571361

13581362

1363+
def linux_official_distro_evidence_audit_report() -> dict[str, Any]:
1364+
"""Return a deterministic release-facing official evidence audit report."""
1365+
drift_errors = linux_official_distro_evidence_drift_errors()
1366+
return {
1367+
"summary": linux_official_distro_evidence_summary(),
1368+
"matrix": list(linux_official_distro_evidence_matrix()),
1369+
"drift_errors": drift_errors,
1370+
"ok": not drift_errors,
1371+
}
1372+
1373+
13591374
def _generated_official_distro_evidence_record(
13601375
row: Mapping[str, Any],
13611376
) -> tuple[LinuxDistroMappingEvidenceRecord | None, str | None]:
@@ -2780,3 +2795,59 @@ def _tool_path_errors(
27802795
except (KeyError, TypeError, ValueError) as exc:
27812796
errors.append(f"{prefix}: {exc}")
27822797
return errors
2798+
2799+
2800+
class _ContractArgumentParser(argparse.ArgumentParser):
2801+
def error(self, message: str) -> None: # type: ignore[override]
2802+
self.print_usage(sys.stderr)
2803+
print(f"{self.prog}: error: {message}", file=sys.stderr)
2804+
raise SystemExit(EXIT_INVALID)
2805+
2806+
2807+
def build_parser() -> argparse.ArgumentParser:
2808+
parser = _ContractArgumentParser(
2809+
prog="f4_linter_linux_provisioning.py",
2810+
description="Audit Linux F4 linter provisioning policy metadata.",
2811+
)
2812+
mode = parser.add_mutually_exclusive_group(required=True)
2813+
mode.add_argument(
2814+
"--official-evidence-audit",
2815+
action="store_true",
2816+
help="print the official distro evidence audit report as JSON",
2817+
)
2818+
mode.add_argument(
2819+
"--check-official-evidence-drift",
2820+
action="store_true",
2821+
help="fail if official distro evidence drift is detected",
2822+
)
2823+
return parser
2824+
2825+
2826+
def _official_evidence_drift_check_message(drift_errors: list[str]) -> str:
2827+
if not drift_errors:
2828+
return "PASS: Linux official distro evidence drift audit clean"
2829+
lines = ["FAIL: Linux official distro evidence drift detected"]
2830+
lines.extend(f"ERROR: {error}" for error in drift_errors)
2831+
return "\n".join(lines)
2832+
2833+
2834+
def main(argv: list[str] | None = None) -> int:
2835+
args = build_parser().parse_args(argv)
2836+
if args.official_evidence_audit:
2837+
print(
2838+
json.dumps(
2839+
linux_official_distro_evidence_audit_report(),
2840+
indent=2,
2841+
sort_keys=True,
2842+
)
2843+
)
2844+
return EXIT_OK
2845+
2846+
drift_errors = linux_official_distro_evidence_drift_errors()
2847+
message = _official_evidence_drift_check_message(drift_errors)
2848+
print(message, file=sys.stderr if drift_errors else sys.stdout)
2849+
return EXIT_OFFICIAL_EVIDENCE_DRIFT if drift_errors else EXIT_OK
2850+
2851+
2852+
if __name__ == "__main__":
2853+
raise SystemExit(main())

tests/packaging/test_f4_linter_linux_provisioning.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
from __future__ import annotations
1515

1616
import json
17+
import subprocess
18+
import sys
1719
from pathlib import Path
1820
from types import ModuleType
1921
from typing import Any
@@ -118,6 +120,23 @@ def _manifest_distro_evidence(
118120
return _manifest_tool(manifest, tool_id)["distro_mapping"]["evidence"]
119121

120122

123+
def _run_linux_provisioning_script(
124+
repo_root: Path,
125+
*args: str,
126+
) -> subprocess.CompletedProcess[str]:
127+
return subprocess.run(
128+
[
129+
sys.executable,
130+
str(repo_root / "scripts/f4_linter_linux_provisioning.py"),
131+
*args,
132+
],
133+
cwd=repo_root,
134+
capture_output=True,
135+
text=True,
136+
check=False,
137+
)
138+
139+
121140
def _complete_verified_evidence(evidence: dict[str, Any]) -> dict[str, Any]:
122141
promoted = dict(evidence)
123142
promoted.update(
@@ -367,6 +386,48 @@ def test_official_distro_evidence_drift_errors_are_empty(
367386
assert linux_helper.linux_official_distro_evidence_drift_errors() == []
368387

369388

389+
def test_official_distro_evidence_audit_report_is_clean(
390+
linux_helper: ModuleType,
391+
) -> None:
392+
report = linux_helper.linux_official_distro_evidence_audit_report()
393+
394+
assert report["ok"] is True
395+
assert report["drift_errors"] == []
396+
assert report["summary"]["official_override_count"] == 6
397+
assert len(report["matrix"]) == 6
398+
assert [(row["artifact_entry_id"], row["tool_id"]) for row in report["matrix"]] == (
399+
list(DEBIAN_OFFICIAL_EVIDENCE_KEYS)
400+
)
401+
402+
403+
def test_official_distro_evidence_audit_cli_prints_json_report(
404+
repo_root: Path,
405+
) -> None:
406+
result = _run_linux_provisioning_script(repo_root, "--official-evidence-audit")
407+
408+
assert result.returncode == 0
409+
assert result.stderr == ""
410+
report = json.loads(result.stdout)
411+
assert report["ok"] is True
412+
assert report["drift_errors"] == []
413+
assert report["summary"]["official_override_count"] == 6
414+
assert report["summary"]["non_debian_override_count"] == 0
415+
assert len(report["matrix"]) == 6
416+
417+
418+
def test_official_distro_evidence_drift_check_cli_passes(
419+
repo_root: Path,
420+
) -> None:
421+
result = _run_linux_provisioning_script(
422+
repo_root,
423+
"--check-official-evidence-drift",
424+
)
425+
426+
assert result.returncode == 0
427+
assert result.stderr == ""
428+
assert result.stdout == "PASS: Linux official distro evidence drift audit clean\n"
429+
430+
370431
def test_official_distro_evidence_drift_comparison_rejects_mismatched_url(
371432
linux_helper: ModuleType,
372433
) -> None:

0 commit comments

Comments
 (0)