From 4eafea130800271f2f4d43b4da1aaaccce3c6b2c Mon Sep 17 00:00:00 2001 From: Ben Selwyn-Smith Date: Tue, 14 Jan 2025 12:18:15 +1000 Subject: [PATCH] chore: add SLSA version value to Provenance table Signed-off-by: Ben Selwyn-Smith --- src/macaron/database/table_definitions.py | 2 +- .../provenance/provenance_extractor.py | 38 ++++++++++++++++--- src/macaron/slsa_analyzer/analyzer.py | 7 +++- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/macaron/database/table_definitions.py b/src/macaron/database/table_definitions.py index d3bc96992..cef57a51f 100644 --- a/src/macaron/database/table_definitions.py +++ b/src/macaron/database/table_definitions.py @@ -479,7 +479,7 @@ class Provenance(ORMBase): component: Mapped["Component"] = relationship(back_populates="provenance") #: The SLSA version. - version: Mapped[str] = mapped_column(String, nullable=False) + version: Mapped[str] = mapped_column(String, nullable=True) #: The SLSA level. slsa_level: Mapped[int] = mapped_column(Integer, default=0) diff --git a/src/macaron/provenance/provenance_extractor.py b/src/macaron/provenance/provenance_extractor.py index 512d77f11..03ab24235 100644 --- a/src/macaron/provenance/provenance_extractor.py +++ b/src/macaron/provenance/provenance_extractor.py @@ -43,10 +43,10 @@ def extract_repo_and_commit_from_provenance(payload: InTotoPayload) -> tuple[str If the extraction process fails for any reason. """ predicate_type = payload.statement.get("predicateType") - if isinstance(payload, InTotoV1Payload): - if predicate_type == "https://slsa.dev/provenance/v1": - return _extract_from_slsa_v1(payload) - elif isinstance(payload, InTotoV01Payload): + if isinstance(payload, InTotoV1Payload) and predicate_type == "https://slsa.dev/provenance/v1": + return _extract_from_slsa_v1(payload) + + if isinstance(payload, InTotoV01Payload): if predicate_type == "https://slsa.dev/provenance/v0.2": return _extract_from_slsa_v02(payload) if predicate_type == "https://slsa.dev/provenance/v0.1": @@ -56,12 +56,40 @@ def extract_repo_and_commit_from_provenance(payload: InTotoPayload) -> tuple[str msg = ( f"Extraction from provenance not supported for versions: " - f"predicate_type {predicate_type}, in-toto {str(type(payload))}." + f"predicate_type {payload.statement.get('predicateType')}, in-toto {str(type(payload))}." ) logger.debug(msg) raise ProvenanceError(msg) +def extract_predicate_version(payload: InTotoPayload) -> str | None: + """Extract and return the SLSA version from the passed payload. + + Parameters + ---------- + payload: InTotoPayload + The payload to extract from. + + Returns + ------- + str | None + The SLSA version, or None if . + """ + predicate_type = payload.statement.get("predicateType") + if isinstance(payload, InTotoV1Payload) and predicate_type == "https://slsa.dev/provenance/v1": + return "SLSA-1.0" + + if isinstance(payload, InTotoV01Payload): + if predicate_type == "https://slsa.dev/provenance/v0.2": + return "SLSA-0.2" + if predicate_type == "https://slsa.dev/provenance/v0.1": + return "SLSA-0.1" + if predicate_type == "https://witness.testifysec.com/attestation-collection/v0.1": + return "WITNESS-0.1" + + return None + + def _extract_from_slsa_v01(payload: InTotoV01Payload) -> tuple[str | None, str | None]: """Extract the repository and commit metadata from the slsa v01 provenance payload.""" predicate: dict[str, JsonType] | None = payload.statement.get("predicate") diff --git a/src/macaron/slsa_analyzer/analyzer.py b/src/macaron/slsa_analyzer/analyzer.py index 68a5454b3..04dc262a9 100644 --- a/src/macaron/slsa_analyzer/analyzer.py +++ b/src/macaron/slsa_analyzer/analyzer.py @@ -41,6 +41,7 @@ from macaron.provenance.provenance_extractor import ( check_if_input_purl_provenance_conflict, check_if_input_repo_provenance_conflict, + extract_predicate_version, extract_repo_and_commit_from_provenance, ) from macaron.provenance.provenance_finder import ProvenanceFinder, find_provenance_from_ci @@ -487,6 +488,9 @@ def run_single( slsa_level = determine_provenance_slsa_level( analyze_ctx, provenance_payload, provenance_is_verified, provenance_l3_verified ) + slsa_version = None + if provenance_payload: + slsa_version = extract_predicate_version(provenance_payload) analyze_ctx.dynamic_data["provenance_info"] = table_definitions.Provenance( component=component, @@ -495,7 +499,8 @@ def run_single( verified=provenance_is_verified, provenance_payload=provenance_payload, slsa_level=slsa_level, - # TODO Add SLSA version, release tag, release digest. + slsa_version=slsa_version, + # TODO Add release tag, release digest. ) if provenance_payload: analyze_ctx.dynamic_data["is_inferred_prov"] = False