diff --git a/src/cmcp_gateway/tee/base.py b/src/cmcp_gateway/tee/base.py index b301f28f..4b4e5620 100644 --- a/src/cmcp_gateway/tee/base.py +++ b/src/cmcp_gateway/tee/base.py @@ -7,6 +7,14 @@ from dataclasses import dataclass from datetime import UTC, datetime +_ALLOWED_PROVIDERS: frozenset[str] = frozenset({ + "sev-snp", + "tdx", + "opaque", + "tpm", + "software-only", +}) + @dataclass class AttestationReport: @@ -20,6 +28,14 @@ class AttestationReport: attestation_validity_seconds: int measurement_note: str | None = None # e.g. "sha1-bank-fallback" + def __post_init__(self) -> None: + if self.provider not in _ALLOWED_PROVIDERS: + raise ValueError( + f"AttestationReport.provider '{self.provider}' is not in the allowed set " + f"{sorted(_ALLOWED_PROVIDERS)}. " + "Custom TEE providers must use one of the allowed provider names." + ) + class TEEProvider(ABC): """Abstract interface all TEE provider implementations satisfy.""" diff --git a/tests/unit/test_tee.py b/tests/unit/test_tee.py index 3ec6e8b3..4669f199 100644 --- a/tests/unit/test_tee.py +++ b/tests/unit/test_tee.py @@ -129,3 +129,37 @@ def test_detect_explicit_software_only_with_dev_mode(dev_config): dev_config.attestation.provider = TEEProviderEnum.SOFTWARE_ONLY provider = detect_provider(dev_config) assert isinstance(provider, SoftwareOnlyProvider) + + +# ── HW-001: AttestationReport provider validation ──────────────────────────── + +def test_attestation_report_unknown_provider_raises(): + """HW-001: unknown provider string must be rejected at AttestationReport construction.""" + from datetime import timezone + + from cmcp_gateway.tee.base import AttestationReport + with pytest.raises(ValueError, match="not in the allowed set"): + AttestationReport( + provider="unknown-cloud-magic", + measurement="sha256:" + "a" * 64, + report_data="aa" * 32, + raw_evidence=None, + attestation_generated_at=datetime.now(tz=timezone.utc), + attestation_validity_seconds=86400, + ) + + +def test_attestation_report_known_providers_accepted(): + """HW-001: all known providers must be accepted.""" + from datetime import timezone + + from cmcp_gateway.tee.base import AttestationReport, _ALLOWED_PROVIDERS + for provider in _ALLOWED_PROVIDERS: + AttestationReport( + provider=provider, + measurement="sha256:" + "a" * 64, + report_data="aa" * 32, + raw_evidence=None, + attestation_generated_at=datetime.now(tz=timezone.utc), + attestation_validity_seconds=86400, + )