Pin lifecycle receipts to the reviewed parity manifest
This commit is contained in:
parent
52fc0a88fe
commit
1c6b7b182e
2 changed files with 41 additions and 0 deletions
|
|
@ -16,10 +16,12 @@ from typing import Any
|
|||
try:
|
||||
from .private_receipt_io import print_private_receipt_summary
|
||||
from .restore_gcp_generated_postgres_snapshot import DEFAULT_RESTORE_SERVICE_ACCOUNT
|
||||
from .verify_postgres_parity_manifest import REVIEWED_MANIFEST_SQL_SHA256
|
||||
from .verify_vps_canonical_snapshot_delta import DELTA_SCHEMA, parse_timestamp, write_private_json
|
||||
except ImportError: # pragma: no cover - direct script execution
|
||||
from private_receipt_io import print_private_receipt_summary
|
||||
from restore_gcp_generated_postgres_snapshot import DEFAULT_RESTORE_SERVICE_ACCOUNT
|
||||
from verify_postgres_parity_manifest import REVIEWED_MANIFEST_SQL_SHA256
|
||||
from verify_vps_canonical_snapshot_delta import DELTA_SCHEMA, parse_timestamp, write_private_json
|
||||
|
||||
SOURCE_SCHEMA = "livingip.sourceSnapshotReceipt.v2"
|
||||
|
|
@ -405,6 +407,11 @@ def verify_lifecycle(
|
|||
and delta_current.get("manifest_sql_sha256")
|
||||
== (current_source.get("manifest") or {}).get("manifest_sql_sha256")
|
||||
and delta_baseline.get("manifest_sql_sha256") == delta_current.get("manifest_sql_sha256"),
|
||||
"source_delta_manifest_sql_reviewed": delta_baseline.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
|
||||
and delta_current.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
|
||||
and (source.get("manifest") or {}).get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
|
||||
and (current_source.get("manifest") or {}).get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
|
||||
and capture_binding.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256,
|
||||
"source_delta_authorizations_bound": delta_baseline.get("capture_authorization_ref")
|
||||
== source.get("capture_authorization_ref")
|
||||
and delta_current.get("capture_authorization_ref") == current_source.get("capture_authorization_ref"),
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ def lifecycle_receipts(tmp_path: Path) -> dict[str, Path]:
|
|||
"provenance_binding_sha256": "c" * 64,
|
||||
"dump_sha256": "a" * 64,
|
||||
"manifest_sha256": "b" * 64,
|
||||
"manifest_sql_sha256": REVIEWED_MANIFEST_SQL_SHA256,
|
||||
"checks": {
|
||||
name: True
|
||||
for name in (
|
||||
|
|
@ -504,6 +505,39 @@ def test_caller_authored_bundle_is_preparation_only_even_when_all_checks_pass(tm
|
|||
assert "current private GCP staging" not in result["strongest_claim_allowed"]
|
||||
|
||||
|
||||
def test_rebound_unreviewed_manifest_sql_digest_fails_closed(tmp_path: Path) -> None:
|
||||
paths = lifecycle_receipts(tmp_path)
|
||||
unreviewed_digest = "f" * 64
|
||||
|
||||
source = json.loads(paths["source_path"].read_text())
|
||||
source["manifest"]["manifest_sql_sha256"] = unreviewed_digest
|
||||
write_json(paths["source_path"], source)
|
||||
current_source = json.loads(paths["current_source_path"].read_text())
|
||||
current_source["manifest"]["manifest_sql_sha256"] = unreviewed_digest
|
||||
write_json(paths["current_source_path"], current_source)
|
||||
|
||||
restore = json.loads(paths["restore_path"].read_text())
|
||||
restore["source"]["capture_receipt"]["sha256"] = sha256(paths["source_path"])
|
||||
restore["source"]["capture_receipt"]["manifest_sql_sha256"] = unreviewed_digest
|
||||
write_json(paths["restore_path"], restore)
|
||||
|
||||
delta = json.loads(paths["source_delta_path"].read_text())
|
||||
delta["baseline"]["capture_receipt_sha256"] = sha256(paths["source_path"])
|
||||
delta["baseline"]["manifest_sql_sha256"] = unreviewed_digest
|
||||
delta["current"]["capture_receipt_sha256"] = sha256(paths["current_source_path"])
|
||||
delta["current"]["manifest_sql_sha256"] = unreviewed_digest
|
||||
write_json(paths["source_delta_path"], delta)
|
||||
|
||||
cleanup = json.loads(paths["cleanup_path"].read_text())
|
||||
cleanup["restore_receipt"]["sha256"] = sha256(paths["restore_path"])
|
||||
write_json(paths["cleanup_path"], cleanup)
|
||||
|
||||
result = verify_lifecycle(**paths)
|
||||
|
||||
assert result["status"] == "fail"
|
||||
assert "source_delta_manifest_sql_reviewed" in result["failed_checks"]
|
||||
|
||||
|
||||
def test_local_parity_or_missing_cleanup_fails_closed(tmp_path: Path) -> None:
|
||||
paths = lifecycle_receipts(tmp_path)
|
||||
parity = json.loads(paths["parity_path"].read_text())
|
||||
|
|
|
|||
Loading…
Reference in a new issue