Skip to content

Commit e885c70

Browse files
ramonpetgrave64jku
andauthored
Fix instantiation in _to_rekor() for optional inclusion promise (#1382)
* betterproto: avoid assigning a var of type Optional[InclusionPromise] to TransparencyLogEntry.inclusion_promise ``` File "/usr/local/google/home/rpetgrave/src/ssp/sigstore-python/sigstore/models.py", line 262, in _to_rekor tlog_entry = rekor_v1.TransparencyLogEntry( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/google/home/rpetgrave/src/ssp/.venv/lib/python3.12/site-packages/pydantic/_internal/_dataclasses.py", line 120, in __init__ s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s) pydantic_core._pydantic_core.ValidationError: 1 validation error for TransparencyLogEntry inclusion_promise Input should be a dictionary or an instance of InclusionPromise [type=dataclass_type, input_value=None, input_type=NoneType] ``` Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * add test Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * Revert "betterproto: avoid assigning a var of type Optional[InclusionPromise] to TransparencyLogEntry.inclusion_promise" This reverts commit 46b0087. Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * cleanup Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * Reapply "betterproto: avoid assigning a var of type Optional[InclusionPromise] to TransparencyLogEntry.inclusion_promise" This reverts commit 43dc468. Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * cleanup Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * format Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * also delete integrated_time Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * lint Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> * remove mention of pydantic in changelog Signed-off-by: Ramon Petgrave <32398091+ramonpetgrave64@users.noreply.github.com> --------- Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com> Signed-off-by: Ramon Petgrave <32398091+ramonpetgrave64@users.noreply.github.com> Co-authored-by: Jussi Kukkonen <jkukkonen@google.com>
1 parent e7c0bee commit e885c70

File tree

4 files changed

+34
-13
lines changed

4 files changed

+34
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ All versions prior to 0.9.0 are untracked.
1515

1616
### Fixed
1717

18+
* Avoid instantiation issues with `TransparencyLogEntry` when `InclusionPromise` is not present.
19+
1820
* TSA: Changed the Timestamp Authority requests to explicitly use sha256 for message digests.
1921
[#1373](https://github.com/sigstore/sigstore-python/pull/1373)
2022

sigstore/models.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,18 +219,22 @@ def _from_dict_rekor(cls, dict_: dict[str, Any]) -> LogEntry:
219219
tree_size=inclusion_proof.tree_size,
220220
)
221221

222+
inclusion_promise: Optional[B64Str] = None
223+
if tlog_entry.inclusion_promise:
224+
inclusion_promise = B64Str(
225+
base64.b64encode(
226+
tlog_entry.inclusion_promise.signed_entry_timestamp
227+
).decode()
228+
)
229+
222230
return LogEntry(
223231
uuid=None,
224232
body=B64Str(base64.b64encode(tlog_entry.canonicalized_body).decode()),
225233
integrated_time=tlog_entry.integrated_time,
226234
log_id=tlog_entry.log_id.key_id.hex(),
227235
log_index=tlog_entry.log_index,
228236
inclusion_proof=parsed_inclusion_proof,
229-
inclusion_promise=B64Str(
230-
base64.b64encode(
231-
tlog_entry.inclusion_promise.signed_entry_timestamp
232-
).decode()
233-
),
237+
inclusion_promise=inclusion_promise,
234238
)
235239

236240
def _to_rekor(self) -> rekor_v1.TransparencyLogEntry:
@@ -239,12 +243,6 @@ def _to_rekor(self) -> rekor_v1.TransparencyLogEntry:
239243
240244
@private
241245
"""
242-
inclusion_promise: rekor_v1.InclusionPromise | None = None
243-
if self.inclusion_promise:
244-
inclusion_promise = rekor_v1.InclusionPromise(
245-
signed_entry_timestamp=base64.b64decode(self.inclusion_promise)
246-
)
247-
248246
inclusion_proof = rekor_v1.InclusionProof(
249247
log_index=self.inclusion_proof.log_index,
250248
root_hash=bytes.fromhex(self.inclusion_proof.root_hash),
@@ -257,10 +255,14 @@ def _to_rekor(self) -> rekor_v1.TransparencyLogEntry:
257255
log_index=self.log_index,
258256
log_id=common_v1.LogId(key_id=bytes.fromhex(self.log_id)),
259257
integrated_time=self.integrated_time,
260-
inclusion_promise=inclusion_promise, # type: ignore[arg-type]
261258
inclusion_proof=inclusion_proof,
262259
canonicalized_body=base64.b64decode(self.body),
263260
)
261+
if self.inclusion_promise:
262+
inclusion_promise = rekor_v1.InclusionPromise(
263+
signed_entry_timestamp=base64.b64decode(self.inclusion_promise)
264+
)
265+
tlog_entry.inclusion_promise = inclusion_promise
264266

265267
# Fill in the appropriate kind
266268
body_entry: ProposedEntry = TypeAdapter(ProposedEntry).validate_json(

test/unit/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def _signing_materials(name: str, client: RekorClient) -> tuple[Path, Bundle]:
113113

114114

115115
@pytest.fixture
116-
def signing_bundle(asset):
116+
def signing_bundle(asset) -> Callable[[str], tuple[Path, Bundle]]:
117117
def _signing_bundle(name: str) -> tuple[Path, Bundle]:
118118
file = asset(name)
119119
bundle_path = asset(f"{name}.sigstore")

test/unit/test_models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ def test_missing_inclusion_proof(self, integrated_time: int):
4343
inclusion_promise=None,
4444
)
4545

46+
def test_missing_inclusion_promise_and_integrated_time_round_trip(
47+
self, signing_bundle
48+
):
49+
"""
50+
Ensures that LogEntry._to_rekor() succeeds even without an inclusion_promise and integrated_time.
51+
"""
52+
bundle: Bundle
53+
_, bundle = signing_bundle("bundle.txt")
54+
_dict = bundle.log_entry._to_rekor().to_dict()
55+
print(_dict)
56+
del _dict["inclusionPromise"]
57+
del _dict["integratedTime"]
58+
entry = LogEntry._from_dict_rekor(_dict)
59+
assert entry.inclusion_promise is None
60+
assert entry._to_rekor() is not None
61+
assert LogEntry._from_dict_rekor(entry._to_rekor().to_dict()) == entry
62+
4663
def test_logentry_roundtrip(self, signing_bundle):
4764
_, bundle = signing_bundle("bundle.txt")
4865

0 commit comments

Comments
 (0)