|
35 | 35 | dist = impl.Distribution.from_file(dist_path) |
36 | 36 | dist_bundle_path = _ASSETS / "rfc8785-0.1.2-py3-none-any.whl.sigstore" |
37 | 37 | dist_attestation_path = _ASSETS / "rfc8785-0.1.2-py3-none-any.whl.attestation" |
| 38 | +pypi_attestations_dist = impl.Distribution.from_file(_ASSETS / "pypi_attestations-0.0.19.tar.gz") |
38 | 39 | pypi_attestations_attestation = _ASSETS / "pypi_attestations-0.0.19.tar.gz.publish.attestation" |
39 | 40 |
|
40 | 41 | # produced by actions/attest@v1 |
|
46 | 47 | gl_signed_dist = impl.Distribution.from_file(gl_signed_dist_path) |
47 | 48 | gl_attestation_path = _ASSETS / "gitlab_oidc_project-0.0.3.tar.gz.publish.attestation" |
48 | 49 |
|
| 50 | +# contains timestamp but still rekor v1 entry from production |
| 51 | +attestation_with_ts = Path(str(pypi_attestations_attestation) + ".with_timestamp") |
| 52 | +# contains timestamp and rekorv2 entry from staging |
| 53 | +attestation_with_rekor2 = Path(str(pypi_attestations_attestation) + ".with_rekor2_timestamp") |
| 54 | + |
49 | 55 |
|
50 | 56 | class TestDistribution: |
51 | 57 | def test_from_file_nonexistent(self, tmp_path: Path) -> None: |
@@ -214,6 +220,46 @@ def test_verify(self) -> None: |
214 | 220 | bundle = attestation.to_bundle() |
215 | 221 | Verifier.staging(offline=True).verify_dsse(bundle, policy.UnsafeNoOp()) |
216 | 222 |
|
| 223 | + def test_verify_with_timestamp(self) -> None: |
| 224 | + # Our checked-in asset has this identity. |
| 225 | + pol = policy. Identity( identity="[email protected]", issuer="https://github.com/login/oauth") |
| 226 | + |
| 227 | + attestation = impl.Attestation.model_validate_json(attestation_with_ts.read_bytes()) |
| 228 | + predicate_type, predicate = attestation.verify(pol, pypi_attestations_dist, offline=True) |
| 229 | + |
| 230 | + assert attestation.statement["_type"] == "https://in-toto.io/Statement/v1" |
| 231 | + assert ( |
| 232 | + predicate_type |
| 233 | + == attestation.statement["predicateType"] |
| 234 | + == "https://docs.pypi.org/attestations/publish/v1" |
| 235 | + ) |
| 236 | + assert predicate is None and attestation.statement["predicate"] is None |
| 237 | + |
| 238 | + # convert the attestation to a bundle and verify it that way too |
| 239 | + bundle = attestation.to_bundle() |
| 240 | + Verifier.production(offline=True).verify_dsse(bundle, policy.UnsafeNoOp()) |
| 241 | + |
| 242 | + def test_verify_with_timestamp_and_rekor2_entry(self) -> None: |
| 243 | + # Our checked-in asset has this identity. |
| 244 | + pol = policy. Identity( identity="[email protected]", issuer="https://github.com/login/oauth") |
| 245 | + |
| 246 | + attestation = impl.Attestation.model_validate_json(attestation_with_rekor2.read_bytes()) |
| 247 | + predicate_type, predicate = attestation.verify( |
| 248 | + pol, pypi_attestations_dist, staging=True, offline=True |
| 249 | + ) |
| 250 | + |
| 251 | + assert attestation.statement["_type"] == "https://in-toto.io/Statement/v1" |
| 252 | + assert ( |
| 253 | + predicate_type |
| 254 | + == attestation.statement["predicateType"] |
| 255 | + == "https://docs.pypi.org/attestations/publish/v1" |
| 256 | + ) |
| 257 | + assert predicate is None and attestation.statement["predicate"] is None |
| 258 | + |
| 259 | + # convert the attestation to a bundle and verify it that way too |
| 260 | + bundle = attestation.to_bundle() |
| 261 | + Verifier.staging(offline=True).verify_dsse(bundle, policy.UnsafeNoOp()) |
| 262 | + |
217 | 263 | def test_verify_digest_mismatch(self, tmp_path: Path) -> None: |
218 | 264 | # Our checked-in asset has this identity. |
219 | 265 | pol = policy.Identity( |
|
0 commit comments