Skip to content

Commit 0b1cb47

Browse files
committed
move purpose from rekor client to trusted_root
Signed-off-by: Javan lacerda <javanlacerda@google.com>
1 parent 397e166 commit 0b1cb47

File tree

7 files changed

+77
-67
lines changed

7 files changed

+77
-67
lines changed

sigstore/_cli.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,13 @@ def _sign(args: argparse.Namespace) -> None:
649649
signing_ctx = SigningContext.production()
650650
else:
651651
# Assume "production" trust root if no keys are given as arguments
652-
trusted_root = TrustedRoot.production()
653-
trusted_root.set_args(args)
652+
trusted_root = TrustedRoot.production(args=args, purpose=KeyringPurpose.SIGN)
654653
if args.ctfe_pem is not None:
655654
ctfe_keys = [args.ctfe_pem.read()]
656655
else:
657656
ctfe_keys = trusted_root.get_ctfe_keys()
658657

659-
rekor_keyring = trusted_root.rekor_keyring(KeyringPurpose.SIGN)
658+
rekor_keyring = trusted_root.rekor_keyring()
660659

661660
ct_keyring = CTKeyring(Keyring(ctfe_keys))
662661

@@ -820,14 +819,13 @@ def _collect_verification_state(
820819
if not args.certificate_chain:
821820
_die(args, "Custom Rekor URL used without specifying --certificate-chain")
822821

823-
trusted_root = TrustedRoot.production()
824-
trusted_root.set_args(args=args)
822+
trusted_root = TrustedRoot.production(args=args, purpose=KeyringPurpose.VERIFY)
825823
ct_keys = trusted_root.get_ctfe_keys()
826824

827825
verifier = Verifier(
828826
rekor=RekorClient(
829827
url=args.rekor_url,
830-
rekor_keyring=trusted_root.rekor_keyring(KeyringPurpose.VERIFY),
828+
rekor_keyring=trusted_root.rekor_keyring(),
831829
ct_keyring=CTKeyring(Keyring(ct_keys)),
832830
),
833831
trusted_root=trusted_root,

sigstore/_internal/rekor/client.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
from sigstore._internal.ctfe import CTKeyring
3232
from sigstore._internal.keyring import Keyring
33-
from sigstore._internal.trustroot import KeyringPurpose, RekorKeyring, TrustedRoot
33+
from sigstore._internal.trustroot import RekorKeyring, TrustedRoot
3434
from sigstore.transparency import LogEntry
3535

3636
logger = logging.getLogger(__name__)
@@ -246,15 +246,13 @@ def __del__(self) -> None:
246246
self.session.close()
247247

248248
@classmethod
249-
def production(
250-
cls, trust_root: TrustedRoot, purpose: KeyringPurpose
251-
) -> RekorClient:
249+
def production(cls, trust_root: TrustedRoot) -> RekorClient:
252250
"""
253251
Returns a `RekorClient` populated with the default Rekor production instance.
254252
255253
trust_root must be a `TrustedRoot` for the production TUF repository.
256254
"""
257-
rekor_keyring = trust_root.rekor_keyring(purpose)
255+
rekor_keyring = trust_root.rekor_keyring()
258256
ctfe_keys = trust_root.get_ctfe_keys()
259257

260258
return cls(
@@ -264,13 +262,13 @@ def production(
264262
)
265263

266264
@classmethod
267-
def staging(cls, trust_root: TrustedRoot, purpose: KeyringPurpose) -> RekorClient:
265+
def staging(cls, trust_root: TrustedRoot) -> RekorClient:
268266
"""
269267
Returns a `RekorClient` populated with the default Rekor staging instance.
270268
271269
trust_root must be a `TrustedRoot` for the staging TUF repository.
272270
"""
273-
rekor_keyring = trust_root.rekor_keyring(purpose)
271+
rekor_keyring = trust_root.rekor_keyring()
274272
ctfe_keys = trust_root.get_ctfe_keys()
275273

276274
return cls(

sigstore/_internal/trustroot.py

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,42 +83,74 @@ def __str__(self) -> str:
8383
class TrustedRoot(_TrustedRoot):
8484
"""Complete set of trusted entities for a Sigstore client"""
8585

86-
def __init__(self, args: Optional[Namespace] = None):
87-
self.args = args
86+
args: Optional[Namespace] = None
87+
purpose: KeyringPurpose
8888

8989
@classmethod
90-
def from_file(cls, path: str) -> "TrustedRoot":
90+
def from_file(
91+
cls,
92+
path: str,
93+
args: Optional[Namespace] = None,
94+
purpose: KeyringPurpose = KeyringPurpose.VERIFY,
95+
) -> "TrustedRoot":
9196
"""Create a new trust root from file"""
92-
tr: TrustedRoot = cls().from_json(Path(path).read_bytes())
93-
return tr
97+
trusted_root: TrustedRoot = cls().from_json(Path(path).read_bytes())
98+
trusted_root.args = args
99+
trusted_root.purpose = purpose
100+
return trusted_root
94101

95102
@classmethod
96-
def from_tuf(cls, url: str, offline: bool = False) -> "TrustedRoot":
103+
def from_tuf(
104+
cls,
105+
url: str,
106+
offline: bool = False,
107+
args: Optional[Namespace] = None,
108+
purpose: KeyringPurpose = KeyringPurpose.VERIFY,
109+
) -> "TrustedRoot":
97110
"""Create a new trust root from a TUF repository.
98111
99112
If `offline`, will use trust root in local TUF cache. Otherwise will
100113
update the trust root from remote TUF repository.
101114
"""
102115
path = TrustUpdater(url, offline).get_trusted_root_path()
103-
return cls.from_file(path)
116+
trusted_root = cls.from_file(path)
117+
trusted_root.args = args
118+
trusted_root.purpose = purpose
119+
return trusted_root
104120

105121
@classmethod
106-
def production(cls, offline: bool = False) -> "TrustedRoot":
122+
def production(
123+
cls,
124+
offline: bool = False,
125+
args: Optional[Namespace] = None,
126+
purpose: KeyringPurpose = KeyringPurpose.VERIFY,
127+
) -> "TrustedRoot":
107128
"""Create new trust root from Sigstore production TUF repository.
108129
109130
If `offline`, will use trust root in local TUF cache. Otherwise will
110131
update the trust root from remote TUF repository.
111132
"""
112-
return cls.from_tuf(DEFAULT_TUF_URL, offline)
133+
trusted_root = cls.from_tuf(DEFAULT_TUF_URL, offline)
134+
trusted_root.args = args
135+
trusted_root.purpose = purpose
136+
return trusted_root
113137

114138
@classmethod
115-
def staging(cls, offline: bool = False) -> "TrustedRoot":
139+
def staging(
140+
cls,
141+
offline: bool = False,
142+
args: Optional[Namespace] = None,
143+
purpose: KeyringPurpose = KeyringPurpose.VERIFY,
144+
) -> "TrustedRoot":
116145
"""Create new trust root from Sigstore staging TUF repository.
117146
118147
If `offline`, will use trust root in local TUF cache. Otherwise will
119148
update the trust root from remote TUF repository.
120149
"""
121-
return cls.from_tuf(STAGING_TUF_URL, offline)
150+
trusted_root = cls.from_tuf(STAGING_TUF_URL, offline)
151+
trusted_root.args = args
152+
trusted_root.purpose = purpose
153+
return trusted_root
122154

123155
@staticmethod
124156
def _get_tlog_keys(
@@ -147,13 +179,10 @@ def _get_ca_keys(
147179
for cert in ca.cert_chain.certificates:
148180
yield cert.raw_bytes
149181

150-
def set_args(self, args: Namespace) -> None:
151-
self.args = args
152-
153-
def rekor_keyring(self, purpose: KeyringPurpose) -> RekorKeyring:
182+
def rekor_keyring(self) -> RekorKeyring:
154183
"""Return public key contents given certificate authorities."""
155184

156-
return RekorKeyring(self._get_rekor_keys(purpose))
185+
return RekorKeyring(self._get_rekor_keys())
157186

158187
def get_ctfe_keys(self) -> list[bytes]:
159188
"""Return the CTFE public keys contents."""
@@ -164,13 +193,13 @@ def get_ctfe_keys(self) -> list[bytes]:
164193
raise MetadataError("CTFE keys not found in trusted root")
165194
return ctfes
166195

167-
def _get_rekor_keys(self, purpose: KeyringPurpose) -> Keyring:
196+
def _get_rekor_keys(self) -> Keyring:
168197
"""Return the rekor public key content."""
169198
keys: list[bytes]
170199
if self.args and self.args.rekor_root_pubkey:
171200
keys = self.args.rekor_root_pubkey.read()
172201
else:
173-
keys = list(self._get_tlog_keys(self.tlogs, purpose))
202+
keys = list(self._get_tlog_keys(self.tlogs, self.purpose))
174203
if len(keys) != 1:
175204
raise MetadataError("Did not find one Rekor key in trusted root")
176205
return Keyring(keys)

sigstore/sign.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ def production(cls) -> SigningContext:
300300
"""
301301
Return a `SigningContext` instance configured against Sigstore's production-level services.
302302
"""
303-
trusted_root = TrustedRoot.production()
304-
rekor = RekorClient.production(trusted_root, purpose=KeyringPurpose.SIGN)
303+
trusted_root = TrustedRoot.production(purpose=KeyringPurpose.SIGN)
304+
rekor = RekorClient.production(trusted_root)
305305
return cls(
306306
fulcio=FulcioClient.production(), rekor=rekor, trusted_root=trusted_root
307307
)
@@ -311,8 +311,8 @@ def staging(cls) -> SigningContext:
311311
"""
312312
Return a `SignerContext` instance configured against Sigstore's staging-level services.
313313
"""
314-
trusted_root = TrustedRoot.staging()
315-
rekor = RekorClient.staging(trusted_root, purpose=KeyringPurpose.SIGN)
314+
trusted_root = TrustedRoot.staging(purpose=KeyringPurpose.SIGN)
315+
rekor = RekorClient.staging(trusted_root)
316316
return cls(
317317
fulcio=FulcioClient.staging(), rekor=rekor, trusted_root=trusted_root
318318
)

sigstore/verify/verifier.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ def production(cls) -> Verifier:
130130
"""
131131
Return a `Verifier` instance configured against Sigstore's production-level services.
132132
"""
133-
trusted_root = TrustedRoot.production()
133+
trusted_root = TrustedRoot.production(purpose=KeyringPurpose.VERIFY)
134134
return cls(
135-
rekor=RekorClient.production(trusted_root, KeyringPurpose.VERIFY),
135+
rekor=RekorClient.production(trusted_root),
136136
trusted_root=trusted_root,
137137
)
138138

@@ -141,9 +141,9 @@ def staging(cls) -> Verifier:
141141
"""
142142
Return a `Verifier` instance configured against Sigstore's staging-level services.
143143
"""
144-
trusted_root = TrustedRoot.staging()
144+
trusted_root = TrustedRoot.staging(purpose=KeyringPurpose.VERIFY)
145145
return cls(
146-
rekor=RekorClient.staging(trusted_root, KeyringPurpose.VERIFY),
146+
rekor=RekorClient.staging(trusted_root),
147147
trusted_root=trusted_root,
148148
)
149149

test/unit/internal/test_trust_root.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_trust_root_tuf_caches_and_requests(mock_staging_tuf, tuf_dirs):
3737
# keep track of requests the TrustUpdater invoked by TrustedRoot makes
3838
reqs, fail_reqs = mock_staging_tuf
3939

40-
trust_root = TrustedRoot.staging()
40+
trust_root = TrustedRoot.staging(purpose=KeyringPurpose.VERIFY)
4141
# metadata was "downloaded" from staging
4242
expected = ["root.json", "snapshot.json", "targets.json", "timestamp.json"]
4343
assert sorted(os.listdir(data_dir)) == expected
@@ -54,14 +54,14 @@ def test_trust_root_tuf_caches_and_requests(mock_staging_tuf, tuf_dirs):
5454
assert fail_reqs == expected_fail_reqs
5555

5656
trust_root.get_ctfe_keys()
57-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)
57+
trust_root.rekor_keyring()
5858

5959
# no new requests
6060
assert reqs == expected_requests
6161
assert fail_reqs == expected_fail_reqs
6262

6363
# New trust root (and TrustUpdater instance), same cache dirs
64-
trust_root = TrustedRoot.staging()
64+
trust_root = TrustedRoot.staging(purpose=KeyringPurpose.VERIFY)
6565

6666
# Expect new timestamp and root requests
6767
expected_requests["timestamp.json"] += 1
@@ -70,7 +70,7 @@ def test_trust_root_tuf_caches_and_requests(mock_staging_tuf, tuf_dirs):
7070
assert fail_reqs == expected_fail_reqs
7171

7272
trust_root.get_ctfe_keys()
73-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)
73+
trust_root.rekor_keyring()
7474
# Expect no requests
7575
assert reqs == expected_requests
7676
assert fail_reqs == expected_fail_reqs
@@ -83,7 +83,7 @@ def test_trust_root_tuf_offline(mock_staging_tuf, tuf_dirs):
8383
# keep track of requests the TrustUpdater invoked by TrustedRoot makes
8484
reqs, fail_reqs = mock_staging_tuf
8585

86-
trust_root = TrustedRoot.staging(offline=True)
86+
trust_root = TrustedRoot.staging(offline=True, purpose=KeyringPurpose.VERIFY)
8787

8888
# Only the embedded root is in local TUF metadata, nothing is downloaded
8989
expected = ["root.json"]
@@ -92,7 +92,7 @@ def test_trust_root_tuf_offline(mock_staging_tuf, tuf_dirs):
9292
assert fail_reqs == {}
9393

9494
trust_root.get_ctfe_keys()
95-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)
95+
trust_root.rekor_keyring()
9696

9797
# Still no requests
9898
assert reqs == {}
@@ -158,37 +158,22 @@ def _pem_keys(keys):
158158
]
159159

160160
# Assert that trust root from TUF contains the expected keys/certs
161-
trust_root = TrustedRoot.staging()
161+
trust_root = TrustedRoot.staging(purpose=KeyringPurpose.VERIFY)
162162
assert ctfe_keys[0] in _der_keys(trust_root.get_ctfe_keys())
163-
assert (
164-
get_public_bytes(
165-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)._keyring.values()
166-
)
167-
== rekor_keys
168-
)
163+
assert get_public_bytes(trust_root.rekor_keyring()._keyring.values()) == rekor_keys
169164
assert trust_root.get_fulcio_certs() == fulcio_certs
170165

171166
# Assert that trust root from offline TUF contains the expected keys/certs
172-
trust_root = TrustedRoot.staging(offline=True)
167+
trust_root = TrustedRoot.staging(offline=True, purpose=KeyringPurpose.VERIFY)
173168
assert ctfe_keys[0] in _der_keys(trust_root.get_ctfe_keys())
174-
assert (
175-
get_public_bytes(
176-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)._keyring.values()
177-
)
178-
== rekor_keys
179-
)
169+
assert get_public_bytes(trust_root.rekor_keyring()._keyring.values()) == rekor_keys
180170
assert trust_root.get_fulcio_certs() == fulcio_certs
181171

182172
# Assert that trust root from file contains the expected keys/certs
183173
path = tuf_asset.target_path("trusted_root.json")
184174
trust_root = TrustedRoot.from_file(path)
185175
assert ctfe_keys[0] in _der_keys(trust_root.get_ctfe_keys())
186-
assert (
187-
get_public_bytes(
188-
trust_root.rekor_keyring(KeyringPurpose.VERIFY)._keyring.values()
189-
)
190-
== rekor_keys
191-
)
176+
assert get_public_bytes(trust_root.rekor_keyring()._keyring.values()) == rekor_keys
192177
assert trust_root.get_fulcio_certs() == fulcio_certs
193178

194179

test/unit/verify/test_models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def test_verification_materials_retrieves_rekor_entry(self, signing_materials):
5252
file, materials = signing_materials("a.txt")
5353
assert materials._rekor_entry is None
5454

55-
trust_root = TrustedRoot.staging()
56-
client = RekorClient.staging(trust_root, KeyringPurpose.VERIFY)
55+
trust_root = TrustedRoot.staging(purpose=KeyringPurpose.VERIFY)
56+
client = RekorClient.staging(trust_root)
5757

5858
with file.open(mode="rb", buffering=0) as input_:
5959
digest = _sha256_streaming(input_)

0 commit comments

Comments
 (0)