Skip to content

Commit

Permalink
Handle exceptions when doing PyPI -> Sigstore conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
facutuesca committed May 6, 2024
1 parent 3d61baf commit e9c9f1c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/pypi_attestation_models/_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
from typing import TYPE_CHECKING, Annotated, Any, Literal, NewType

import rfc8785
import sigstore.errors
from annotated_types import MinLen # noqa: TCH002
from cryptography import x509
from cryptography.hazmat.primitives import serialization
from pydantic import BaseModel
from pydantic_core import ValidationError
from sigstore.models import Bundle, LogEntry

if TYPE_CHECKING:
Expand Down Expand Up @@ -123,9 +125,18 @@ def pypi_to_sigstore(pypi_attestation: Attestation) -> Bundle:
raise InvalidAttestationError(str(err)) from err

tlog_entry = pypi_attestation.verification_material.transparency_entries[0]
try:
certificate = x509.load_der_x509_certificate(certificate_bytes)
except ValueError as err:
raise InvalidAttestationError(str(err)) from err

try:
log_entry = LogEntry._from_dict_rekor(tlog_entry) # noqa: SLF001
except (ValidationError, sigstore.errors.Error) as err:
raise InvalidAttestationError(str(err)) from err

return Bundle.from_parts(
cert=x509.load_der_x509_certificate(certificate_bytes),
cert=certificate,
sig=signature_bytes,
log_entry=LogEntry._from_dict_rekor(tlog_entry), # noqa: SLF001
log_entry=log_entry,
)
19 changes: 19 additions & 0 deletions test/test_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ def test_pypi_to_sigstore_invalid_certificate_base64() -> None:
impl.pypi_to_sigstore(attestation)


def test_pypi_to_sigstore_invalid_certificate() -> None:
with attestation_path.open("rb") as f:
attestation = impl.Attestation.model_validate_json(f.read())
new_cert = attestation.verification_material.certificate.replace("M", "x")
attestation.verification_material.certificate = new_cert
with pytest.raises(impl.InvalidAttestationError):
impl.pypi_to_sigstore(attestation)


def test_pypi_to_sigstore_invalid_log_entry() -> None:
with attestation_path.open("rb") as f:
attestation = impl.Attestation.model_validate_json(f.read())
new_log_entry = attestation.verification_material.transparency_entries[0]
del new_log_entry["inclusionProof"]
attestation.verification_material.transparency_entries = [new_log_entry]
with pytest.raises(impl.InvalidAttestationError):
impl.pypi_to_sigstore(attestation)


def test_verification_roundtrip() -> None:
# Load an existing Sigstore bundle, check that verification passes,
# convert it to a PyPI attestation and then back again to a Sigstore
Expand Down

0 comments on commit e9c9f1c

Please sign in to comment.