62 lines
3.0 KiB
Python
62 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "active-runtime" / "app"))
|
|
from trusted_release_execution_plan import PlanError, TrustedReleasePlan, canonical_json
|
|
|
|
|
|
def plan():
|
|
return {
|
|
"schema": "aios.trusted-release-execution-plan.v1",
|
|
"version": "V2R2C2",
|
|
"candidate_id": "rc-v2r2c2-contract-001",
|
|
"source_commit": "1" * 40,
|
|
"tree_oid": "2" * 40,
|
|
"artifact_sha256": "3" * 64,
|
|
"manifest_sha256": "4" * 64,
|
|
"package_closure_sha256": "5" * 64,
|
|
"deployment_plan_sha256": "6" * 64,
|
|
"policy_sha256": "7" * 64,
|
|
"release_plan_id": "sha256:" + "8" * 64,
|
|
"approval_plan_id": "sha256:" + "9" * 64,
|
|
"evidence_closure_oid": "a" * 40,
|
|
"campaign_authorization_sha256": "b" * 64,
|
|
"campaign_generation": 4,
|
|
"artifact": {"path": "/var/lib/aios/releases/V2R2C2/artifact.tar.zst", "size": 123},
|
|
"rollback": {"version": "V2R2C1", "target_oid": "c" * 40, "artifact_sha256": "d" * 64},
|
|
"baseline": {"version": "V2R2C1", "target_oid": "c" * 40},
|
|
"adapter_policy": {"policy_id": "aios.production-adapter.allowlisted.v1", "service": "aios-gitops-model-api", "port": 18927},
|
|
}
|
|
|
|
|
|
def test_plan_digest_is_recomputed_and_binding_is_exact():
|
|
value = plan()
|
|
parsed = TrustedReleasePlan.from_mapping(value)
|
|
assert parsed.release_plan_sha256 == hashlib.sha256(canonical_json(value)).hexdigest()
|
|
assert parsed.candidate_binding_sha256 == hashlib.sha256(canonical_json({k: value[k] for k in ("candidate_id", "source_commit", "tree_oid", "artifact_sha256", "manifest_sha256")})).hexdigest()
|
|
parsed.assert_binding({"version": "V2R2C2", "target_oid": "1" * 40, "evidence_closure_oid": "a" * 40, "artifact_sha256": "3" * 64, "artifact_size": 123, "approval_plan_id": "sha256:" + "9" * 64, "candidate_id": "rc-v2r2c2-contract-001"})
|
|
|
|
|
|
def test_claimed_digest_or_candidate_tamper_fails_closed():
|
|
value = plan()
|
|
value["release_plan_sha256"] = "f" * 64
|
|
with pytest.raises(PlanError, match="release_plan_sha256_mismatch"):
|
|
TrustedReleasePlan.from_mapping(value)
|
|
value = plan()
|
|
value["candidate_id"] = "different-candidate"
|
|
parsed = TrustedReleasePlan.from_mapping(value)
|
|
with pytest.raises(PlanError, match="binding_plan_mismatch"):
|
|
parsed.assert_binding({"version": "V2R2C2", "target_oid": "1" * 40, "evidence_closure_oid": "a" * 40, "artifact_sha256": "3" * 64, "artifact_size": 123, "approval_plan_id": "sha256:" + "9" * 64, "candidate_id": "rc-v2r2c2-contract-001"})
|
|
|
|
|
|
def test_plan_cannot_supply_executable_or_shell_path():
|
|
value = plan()
|
|
value["adapter_policy"] = {"policy_id": "aios.production-adapter.allowlisted.v1", "service": "aios-gitops-model-api", "port": 18927, "executable": "/tmp/evil"}
|
|
with pytest.raises(PlanError, match="release_plan_fields_invalid|forbidden_plan_key"):
|
|
TrustedReleasePlan.from_mapping(value)
|