Skip to content

Commit 7a82a46

Browse files
committed
Merge remote-tracking branch 'origin/main' into ww/rm-protobufs
2 parents 9782545 + 77c4b8c commit 7a82a46

File tree

4 files changed

+51
-27
lines changed

4 files changed

+51
-27
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ jobs:
128128
- run: pip install coverage[toml]
129129

130130
- name: download coverage data
131-
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
131+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
132132
with:
133133
path: all-artifacts/
134134

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
attestations: write # To persist the attestation files.
9595
steps:
9696
- name: Download artifacts directories # goes to current working directory
97-
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
97+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
9898
- name: Generate build provenance
9999
uses: actions/attest-build-provenance@v2
100100
with:
@@ -108,7 +108,7 @@ jobs:
108108
id-token: write
109109
steps:
110110
- name: Download artifacts directories # goes to current working directory
111-
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
111+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
112112

113113
- name: publish
114114
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
@@ -123,7 +123,7 @@ jobs:
123123
contents: write
124124
steps:
125125
- name: Download artifacts directories # goes to current working directory
126-
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
126+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
127127

128128
- name: Upload artifacts to github
129129
# Confusingly, this action also supports updating releases, not

sigstore/verify/verifier.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@
6262
# From https://github.com/sigstore/sigstore-go/blob/e92142f0734064ebf6001f188b7330a1212245fe/pkg/verify/tsa.go#L29
6363
MAX_ALLOWED_TIMESTAMP: int = 32
6464

65-
# When verifying a timestamp, this threshold represents the minimum number of required
66-
# timestamps to consider a signature valid.
67-
VERIFY_TIMESTAMP_THRESHOLD: int = 1
65+
# When verifying an entry, this threshold represents the minimum number of required
66+
# verified times to consider a signature valid.
67+
VERIFIED_TIME_THRESHOLD: int = 1
6868

6969

7070
class Verifier:
@@ -219,13 +219,6 @@ def _establish_time(self, bundle: Bundle) -> list[TimestampVerificationResult]:
219219
raise VerificationError(msg)
220220

221221
timestamp_from_tsa = self._verify_timestamp_authority(bundle)
222-
if len(timestamp_from_tsa) < VERIFY_TIMESTAMP_THRESHOLD:
223-
msg = (
224-
f"not enough timestamps validated to meet the validation "
225-
f"threshold ({len(timestamp_from_tsa)}/{VERIFY_TIMESTAMP_THRESHOLD})"
226-
)
227-
raise VerificationError(msg)
228-
229222
verified_timestamps.extend(timestamp_from_tsa)
230223

231224
# If a timestamp from the Transparency Service is available, the Verifier MUST
@@ -236,6 +229,12 @@ def _establish_time(self, bundle: Bundle) -> list[TimestampVerificationResult]:
236229
if (
237230
timestamp := bundle.log_entry._inner.integrated_time
238231
) and bundle.log_entry._inner.inclusion_promise:
232+
kv = bundle.log_entry._inner.kind_version
233+
if not (kv.kind in ["dsse", "hashedrekord"] and kv.version == "0.0.1"):
234+
raise VerificationError(
235+
"Integrated time only supported for dsse/hashedrekord 0.0.1 types"
236+
)
237+
239238
verified_timestamps.append(
240239
TimestampVerificationResult(
241240
source=TimestampSource.TRANSPARENCY_SERVICE,
@@ -324,13 +323,12 @@ def _verify_common_signing_cert(
324323
store.add_cert(parent_cert_ossl)
325324

326325
# (0): Establishing a Time for the Signature
327-
# First, establish a time for the signature. This timestamp is required to
326+
# First, establish verified times for the signature. This is required to
328327
# validate the certificate chain, so this step comes first.
329-
# While this step is optional and only performed if timestamp data has been
330-
# provided within the bundle, providing a signed timestamp without a TSA to
331-
# verify it result in a VerificationError.
328+
# These include TSA timestamps and (in the case of rekor v1 entries)
329+
# rekor log integrated time.
332330
verified_timestamps = self._establish_time(bundle)
333-
if not verified_timestamps:
331+
if len(verified_timestamps) < VERIFIED_TIME_THRESHOLD:
334332
raise VerificationError("not enough sources of verified time")
335333

336334
# (1): verify that the signing certificate is signed by the root

test/unit/verify/test_verifier.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ def verifier(self, asset) -> Verifier:
219219
verifier._trusted_root._inner.timestamp_authorities = [authority._inner]
220220
return verifier
221221

222-
def test_verifier_verify_timestamp(self, verifier, asset, null_policy):
222+
def test_verifier_verify_timestamp(self, verifier, asset, null_policy, monkeypatch):
223+
# asset is a rekor v1 bundle: set threshold to 2 so both integrated time and the
224+
# TSA timestamp are required
225+
monkeypatch.setattr("sigstore.verify.verifier.VERIFIED_TIME_THRESHOLD", 2)
226+
223227
verifier.verify_artifact(
224228
asset("tsa/bundle.txt").read_bytes(),
225229
Bundle.from_json(asset("tsa/bundle.txt.sigstore").read_bytes()),
@@ -297,15 +301,21 @@ def test_verifier_duplicate_timestamp(self, verifier, asset, null_policy):
297301
)
298302

299303
def test_verifier_outside_validity_range(
300-
self, caplog, verifier, asset, null_policy
304+
self, caplog, verifier, asset, null_policy, monkeypatch
301305
):
306+
# asset is a rekor v1 bundle: set threshold to 2 so both integrated time and the
307+
# TSA timestamp are required
308+
monkeypatch.setattr("sigstore.verify.verifier.VERIFIED_TIME_THRESHOLD", 2)
309+
302310
# Set a date before the timestamp range
303311
verifier._trusted_root.get_timestamp_authorities()[
304312
0
305313
]._inner.valid_for.end = datetime(2024, 10, 31, tzinfo=timezone.utc)
306314

307315
with caplog.at_level(logging.DEBUG, logger="sigstore.verify.verifier"):
308-
with pytest.raises(VerificationError, match="not enough timestamps"):
316+
with pytest.raises(
317+
VerificationError, match="not enough sources of verified time"
318+
):
309319
verifier.verify_artifact(
310320
asset("tsa/bundle.txt").read_bytes(),
311321
Bundle.from_json(asset("tsa/bundle.txt.sigstore").read_bytes()),
@@ -320,13 +330,19 @@ def test_verifier_outside_validity_range(
320330
def test_verifier_rfc3161_error(
321331
self, verifier, asset, null_policy, caplog, monkeypatch
322332
):
333+
# asset is a rekor v1 bundle: set threshold to 2 so both integrated time and the
334+
# TSA timestamp are required
335+
monkeypatch.setattr("sigstore.verify.verifier.VERIFIED_TIME_THRESHOLD", 2)
336+
323337
def verify_function(*args):
324338
raise rfc3161_client.VerificationError()
325339

326340
monkeypatch.setattr(rfc3161_client.verify._Verifier, "verify", verify_function)
327341

328342
with caplog.at_level(logging.DEBUG, logger="sigstore.verify.verifier"):
329-
with pytest.raises(VerificationError, match="not enough timestamps"):
343+
with pytest.raises(
344+
VerificationError, match="not enough sources of verified time"
345+
):
330346
verifier.verify_artifact(
331347
asset("tsa/bundle.txt").read_bytes(),
332348
Bundle.from_json(asset("tsa/bundle.txt.sigstore").read_bytes()),
@@ -346,15 +362,21 @@ def test_verifier_no_authorities(self, asset, null_policy):
346362
null_policy,
347363
)
348364

349-
def test_late_timestamp(self, caplog, verifier, asset, null_policy):
365+
def test_late_timestamp(self, caplog, verifier, asset, null_policy, monkeypatch):
350366
"""
351367
Ensures that verifying the signing certificate fails because the timestamp
352368
is outside the certificate's validity window. The sample bundle
353369
"tsa/bundle.txt.late_timestamp.sigstore" was generated by adding `time.sleep(12*60)`
354370
into `sigstore.sign.Signer._finalize_sign()`, just after the entry is posted to Rekor
355371
but before the timestamp is requested.
356372
"""
357-
with pytest.raises(VerificationError, match="not enough timestamps"):
373+
# asset is a rekor v1 bundle: set threshold to 2 so both integrated time and the
374+
# TSA timestamp are required
375+
monkeypatch.setattr("sigstore.verify.verifier.VERIFIED_TIME_THRESHOLD", 2)
376+
377+
with pytest.raises(
378+
VerificationError, match="not enough sources of verified time"
379+
):
358380
verifier.verify_artifact(
359381
asset("tsa/bundle.txt").read_bytes(),
360382
Bundle.from_json(
@@ -371,8 +393,12 @@ def test_late_timestamp(self, caplog, verifier, asset, null_policy):
371393
def test_verifier_not_enough_timestamp(
372394
self, verifier, asset, null_policy, monkeypatch
373395
):
374-
monkeypatch.setattr("sigstore.verify.verifier.VERIFY_TIMESTAMP_THRESHOLD", 2)
375-
with pytest.raises(VerificationError, match="not enough timestamps"):
396+
# asset is a rekor v1 bundle: set threshold to 3 so integrated time and one
397+
# TSA timestamp are not enough
398+
monkeypatch.setattr("sigstore.verify.verifier.VERIFIED_TIME_THRESHOLD", 3)
399+
with pytest.raises(
400+
VerificationError, match="not enough sources of verified time"
401+
):
376402
verifier.verify_artifact(
377403
asset("tsa/bundle.txt").read_bytes(),
378404
Bundle.from_json(asset("tsa/bundle.txt.sigstore").read_bytes()),

0 commit comments

Comments
 (0)