GuestOps/tests/test_debian_acceptance.py

114 lines
4.7 KiB
Python

import importlib.util
from pathlib import Path
import unittest
spec = importlib.util.spec_from_file_location(
"debian_acceptance", Path(__file__).resolve().parents[1] / "deploy" / "debian_acceptance.py")
acceptance = importlib.util.module_from_spec(spec)
spec.loader.exec_module(acceptance)
COMMIT = "a" * 40
RELEASE_SHA = "b" * 64
def common(system):
return {
"schemaVersion": 1,
"system": system,
"evidenceId": acceptance.SYSTEMS[system]["evidenceId"],
"releaseVersion": "0.2.1",
"releaseCommit": COMMIT,
"releaseRecordSha256": RELEASE_SHA,
"archiveSha256": "c" * 64,
"environment": "https://sandbox-guestops.futuresens.co.uk",
"hostIdentifier": "guestops-sandbox-01",
"images": {
"api": {"reference": f"guestops-api:{COMMIT}", "id": "sha256:" + "d" * 64},
"worker": {"reference": f"guestops-worker:{COMMIT}", "id": "sha256:" + "e" * 64},
},
"operator": "Deployment operator",
"reviewedBy": "Independent reviewer",
"startedAt": "2026-09-30T09:00:00Z",
"endedAt": "2026-09-30T10:00:00Z",
"reviewedAt": "2026-09-30T11:00:00Z",
"unresolvedCriticalFindings": 0,
"scenarios": [
{"id": scenario, "status": "pass", "evidence": [f"restricted-{index}"]}
for index, scenario in enumerate(sorted(acceptance.SYSTEMS[system]["scenarios"]), 1)
],
}
def valid_records():
host = common("guestops-debian-host")
host["hostFacts"] = {
"debianMajor": 12,
"cpuCores": 4,
"memoryBytes": 8_140_382_208,
"freeDiskBytes": 14_275_686_400,
"publicTcpPorts": [80, 443],
}
host["featureControls"] = {
"googleSending": "disabled",
"faqLiveMode": "disabled",
"pmsWrites": "disabled",
"paymentCreation": "disabled",
}
persistence = common("guestops-persistence")
persistence["drillCommand"] = "python3 deploy/ops.py persistence-drill --confirm-restart"
return host, persistence
class DebianAcceptanceTests(unittest.TestCase):
def test_complete_matching_records_pass(self):
acceptance.validate_pair(*valid_records(), COMMIT, RELEASE_SHA)
def test_expected_release_identity_is_required(self):
host, persistence = valid_records()
host["releaseCommit"] = "f" * 40
with self.assertRaisesRegex(ValueError, "approved candidate"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
host, persistence = valid_records()
persistence["releaseRecordSha256"] = "f" * 64
with self.assertRaisesRegex(ValueError, "retained release record"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
def test_exact_images_and_cross_record_identity_are_required(self):
host, persistence = valid_records()
host["images"]["api"]["reference"] = "guestops-api:latest"
with self.assertRaisesRegex(ValueError, "full approved commit"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
host, persistence = valid_records()
persistence["archiveSha256"] = "f" * 64
with self.assertRaisesRegex(ValueError, "same archiveSha256"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
def test_host_capacity_ports_and_disabled_controls_are_required(self):
host, persistence = valid_records()
host["hostFacts"]["publicTcpPorts"] = [80, 443, 8080]
with self.assertRaisesRegex(ValueError, "Only TCP ports"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
host, persistence = valid_records()
host["featureControls"]["googleSending"] = "enabled"
with self.assertRaisesRegex(ValueError, "must remain disabled"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
def test_independent_review_scenarios_and_findings_are_required(self):
host, persistence = valid_records()
host["reviewedBy"] = host["operator"]
with self.assertRaisesRegex(ValueError, "different people"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
host, persistence = valid_records()
persistence["scenarios"][0]["status"] = "not-run"
with self.assertRaisesRegex(ValueError, "has not passed"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
host, persistence = valid_records()
host["unresolvedCriticalFindings"] = 1
with self.assertRaisesRegex(ValueError, "critical findings"):
acceptance.validate_pair(host, persistence, COMMIT, RELEASE_SHA)
if __name__ == "__main__":
unittest.main()