Skip to content

Commit 7466e1b

Browse files
authored
API: make _StatementBuilder public (#1077)
1 parent 575124a commit 7466e1b

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ All versions prior to 0.9.0 are untracked.
88

99
## [Unreleased]
1010

11+
### Added
12+
13+
* API: `dsse.StatementBuilder` has been added. It can be used to construct an
14+
in-toto `Statement` for subsequent enveloping and signing.
15+
This API is public but is **not considered stable until the next major
16+
release.**
17+
([#1077](https://github.com/sigstore/sigstore-python/pull/1077))
18+
1119
### Changed
1220

1321
* API: `verify_dsse` now rejects bundles with DSSE envelopes that have more than

sigstore/dsse.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,23 @@ class Statement:
8989
See: <https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md>
9090
"""
9191

92-
def __init__(self, contents: bytes) -> None:
92+
def __init__(self, contents: bytes | _Statement) -> None:
9393
"""
9494
Construct a new Statement.
9595
9696
This takes an opaque `bytes` containing the statement; use
9797
`StatementBuilder` to manually construct an in-toto statement
9898
from constituent pieces.
9999
"""
100-
self._contents = contents
101-
try:
102-
self._inner = _Statement.model_validate_json(contents)
103-
except ValidationError:
104-
raise Error("malformed in-toto statement")
100+
if isinstance(contents, bytes):
101+
self._contents = contents
102+
try:
103+
self._inner = _Statement.model_validate_json(contents)
104+
except ValidationError:
105+
raise Error("malformed in-toto statement")
106+
else:
107+
self._contents = contents.model_dump_json(by_alias=True).encode()
108+
self._inner = contents
105109

106110
def _matches_digest(self, digest: Hashed) -> bool:
107111
"""
@@ -130,7 +134,7 @@ def _pae(self) -> bytes:
130134
return _pae(Envelope._TYPE, self._contents)
131135

132136

133-
class _StatementBuilder:
137+
class StatementBuilder:
134138
"""
135139
A builder-style API for constructing in-toto Statements.
136140
"""
@@ -142,27 +146,27 @@ def __init__(
142146
predicate: Optional[Dict[str, Any]] = None,
143147
):
144148
"""
145-
Create a new `_StatementBuilder`.
149+
Create a new `StatementBuilder`.
146150
"""
147151
self._subjects = subjects or []
148152
self._predicate_type = predicate_type
149153
self._predicate = predicate
150154

151-
def subjects(self, subjects: list[_Subject]) -> _StatementBuilder:
155+
def subjects(self, subjects: list[_Subject]) -> StatementBuilder:
152156
"""
153157
Configure the subjects for this builder.
154158
"""
155159
self._subjects = subjects
156160
return self
157161

158-
def predicate_type(self, predicate_type: str) -> _StatementBuilder:
162+
def predicate_type(self, predicate_type: str) -> StatementBuilder:
159163
"""
160164
Configure the predicate type for this builder.
161165
"""
162166
self._predicate_type = predicate_type
163167
return self
164168

165-
def predicate(self, predicate: dict[str, Any]) -> _StatementBuilder:
169+
def predicate(self, predicate: dict[str, Any]) -> StatementBuilder:
166170
"""
167171
Configure the predicate for this builder.
168172
"""
@@ -183,7 +187,7 @@ def build(self) -> Statement:
183187
except ValidationError as e:
184188
raise Error(f"invalid statement: {e}")
185189

186-
return Statement(stmt.model_dump_json(by_alias=True).encode())
190+
return Statement(stmt)
187191

188192

189193
class Envelope:

test/unit/test_sign.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from sigstore_protobuf_specs.dev.sigstore.common.v1 import HashAlgorithm
2121

2222
import sigstore.oidc
23-
from sigstore.dsse import _StatementBuilder, _Subject
23+
from sigstore.dsse import StatementBuilder, _Subject
2424
from sigstore.errors import VerificationError
2525
from sigstore.hashes import Hashed
2626
from sigstore.sign import SigningContext
@@ -152,7 +152,7 @@ def test_sign_dsse(staging):
152152

153153
ctx = sign_ctx()
154154
stmt = (
155-
_StatementBuilder()
155+
StatementBuilder()
156156
.subjects(
157157
[_Subject(name="null", digest={"sha256": hashlib.sha256(b"").hexdigest()})]
158158
)

test/unit/verify/test_verifier.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import pretend
1919
import pytest
2020

21-
from sigstore.dsse import _StatementBuilder, _Subject
21+
from sigstore.dsse import StatementBuilder, _Subject
2222
from sigstore.errors import VerificationError
2323
from sigstore.models import Bundle
2424
from sigstore.verify import policy
@@ -159,7 +159,7 @@ def test_verifier_dsse_roundtrip(staging):
159159

160160
ctx = signer_cls()
161161
stmt = (
162-
_StatementBuilder()
162+
StatementBuilder()
163163
.subjects(
164164
[_Subject(name="null", digest={"sha256": hashlib.sha256(b"").hexdigest()})]
165165
)

0 commit comments

Comments
 (0)