134 lines
4.5 KiB
Python
134 lines
4.5 KiB
Python
"""Software-only regressions for external bootstrap install evidence."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import hmac
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from tools.rf001_bootstrap_install_orchestrator import (
|
|
EvidencePathError,
|
|
PackageValidationError,
|
|
SIGNATURE_DOMAIN,
|
|
run_installer,
|
|
snapshot_tree,
|
|
validate_pristine_package,
|
|
)
|
|
|
|
|
|
def _sha256(path: Path) -> str:
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def _signed_package(tmp_path: Path) -> tuple[Path, Path]:
|
|
package = tmp_path / "clean-bootstrap"
|
|
package.mkdir()
|
|
(package / "INSTALL_RX_AGENT.cmd").write_text("@echo off\n", encoding="utf-8")
|
|
payload = package / "payload.bin"
|
|
payload.write_bytes(b"fixed bootstrap payload")
|
|
rows = []
|
|
for path in sorted(item for item in package.rglob("*") if item.is_file()):
|
|
rows.append(
|
|
{
|
|
"path": path.relative_to(package).as_posix(),
|
|
"bytes": path.stat().st_size,
|
|
"sha256": _sha256(path),
|
|
}
|
|
)
|
|
manifest = {
|
|
"schema_version": 1,
|
|
"package_kind": "BOOTSTRAP",
|
|
"bootstrap_id": "rf001-bootstrap-2099.01.01.1",
|
|
"agent_release_id": "rf001-agent-2099.01.01.1",
|
|
"agent_version": "2099.01.01.1",
|
|
"files": rows,
|
|
}
|
|
manifest_bytes = (
|
|
json.dumps(manifest, sort_keys=True, separators=(",", ":")) + "\n"
|
|
).encode("utf-8")
|
|
(package / "BOOTSTRAP_MANIFEST.json").write_bytes(manifest_bytes)
|
|
token = tmp_path / "token.txt"
|
|
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
|
|
signature = hmac.new(
|
|
token.read_text(encoding="utf-8").encode("utf-8"),
|
|
SIGNATURE_DOMAIN + manifest_bytes,
|
|
hashlib.sha256,
|
|
).hexdigest()
|
|
(package / "BOOTSTRAP_MANIFEST.hmac").write_text(
|
|
signature + "\n",
|
|
encoding="ascii",
|
|
)
|
|
return package, token
|
|
|
|
|
|
def test_pristine_package_uses_external_logs_and_remains_unchanged(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
package, token = _signed_package(tmp_path)
|
|
evidence = tmp_path / "external-evidence"
|
|
before = snapshot_tree(package)
|
|
command = [
|
|
sys.executable,
|
|
"-c",
|
|
"import sys; print('installer stdout'); print('installer stderr', file=sys.stderr)",
|
|
]
|
|
|
|
result = run_installer(package, evidence, token, command=command)
|
|
|
|
assert result["exit_code"] == 0
|
|
assert result["package_content_unchanged_immediate"] is True
|
|
assert result["package_content_unchanged_after"] is True
|
|
assert result["package_metadata_unchanged_after"] is True
|
|
assert snapshot_tree(package) == before
|
|
assert (evidence / "install.stdout.txt").read_text().strip() == "installer stdout"
|
|
assert (evidence / "install.stderr.txt").read_text().strip() == "installer stderr"
|
|
assert not (package / "install.stdout.txt").exists()
|
|
assert not (package / "install.stderr.txt").exists()
|
|
preflight = json.loads((evidence / "package_preflight.json").read_text())
|
|
assert preflight["hmac"] == "PASS"
|
|
assert preflight["unexpected"] == 0
|
|
assert preflight["missing"] == 0
|
|
|
|
|
|
def test_contaminated_package_fails_closed_before_command(tmp_path: Path) -> None:
|
|
package, token = _signed_package(tmp_path)
|
|
(package / "install.stdout.txt").write_text("orchestration leak\n", encoding="utf-8")
|
|
evidence = tmp_path / "external-evidence"
|
|
command_marker = tmp_path / "command-ran.txt"
|
|
command = [
|
|
sys.executable,
|
|
"-c",
|
|
f"from pathlib import Path; Path({str(command_marker)!r}).write_text('ran')",
|
|
]
|
|
|
|
with pytest.raises(PackageValidationError, match="allowlist mismatch"):
|
|
run_installer(package, evidence, token, command=command)
|
|
|
|
assert not command_marker.exists()
|
|
assert not (evidence / "install.stdout.txt").exists()
|
|
assert not (evidence / "install.stderr.txt").exists()
|
|
|
|
|
|
def test_evidence_directory_inside_package_is_rejected(tmp_path: Path) -> None:
|
|
package, token = _signed_package(tmp_path)
|
|
evidence = package / "runtime-evidence"
|
|
|
|
with pytest.raises(EvidencePathError, match="outside the package"):
|
|
run_installer(package, evidence, token, command=[sys.executable, "-c", "pass"])
|
|
|
|
|
|
def test_pristine_validation_reports_exact_allowlist(tmp_path: Path) -> None:
|
|
package, token = _signed_package(tmp_path)
|
|
|
|
result = validate_pristine_package(package, token)
|
|
|
|
assert result["hmac"] == "PASS"
|
|
assert result["manifest_file_count"] == 2
|
|
assert result["package_file_count"] == 4
|
|
assert result["unexpected"] == 0
|
|
assert result["missing"] == 0
|