Skip to content

Commit 20cbe79

Browse files
authored
Upgrade to tuf 6.0 (sigstore#1323)
The big changes in tuf internal: * no longer uses request * no longer uses certifi The included code change in this PR is not strictly necessary but is potentially a little more secure (client no longer trusts the metadata cache but always initializes the Updater from the embedded root). The test changes are related to * assumptions we make on the tuf metadata cache content * our tests mocking a feature that was changed in TUF (RequestsFetcher got changed to Urllib3Fetcher) Signed-off-by: Jussi Kukkonen <[email protected]>
1 parent 1c95fa9 commit 20cbe79

File tree

4 files changed

+17
-22
lines changed

4 files changed

+17
-22
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dependencies = [
4040
# NOTE(ww): Both under active development, so strictly pinned.
4141
"sigstore-protobuf-specs == 0.3.2",
4242
"sigstore-rekor-types == 0.0.18",
43-
"tuf ~= 5.0",
43+
"tuf ~= 6.0",
4444
"platformdirs ~= 4.2",
4545
]
4646
requires-python = ">=3.9"

sigstore/_internal/tuf.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,6 @@ def __init__(self, url: str, offline: bool = False) -> None:
8787
else:
8888
raise RootError
8989

90-
# Initialize metadata dir
91-
self._metadata_dir.mkdir(parents=True, exist_ok=True)
92-
tuf_root = self._metadata_dir / "root.json"
93-
94-
if not tuf_root.exists():
95-
try:
96-
root_json = read_embedded("root.json", rsrc_prefix)
97-
except FileNotFoundError as e:
98-
raise RootError from e
99-
100-
tuf_root.write_bytes(root_json)
101-
10290
# Initialize targets cache dir
10391
self._targets_dir.mkdir(parents=True, exist_ok=True)
10492
trusted_root_target = self._targets_dir / "trusted_root.json"
@@ -121,12 +109,17 @@ def __init__(self, url: str, offline: bool = False) -> None:
121109
)
122110
else:
123111
# Initialize and update the toplevel TUF metadata
112+
try:
113+
root_json = read_embedded("root.json", rsrc_prefix)
114+
except FileNotFoundError as e:
115+
raise RootError from e
124116
self._updater = Updater(
125117
metadata_dir=str(self._metadata_dir),
126118
metadata_base_url=self._repo_url,
127119
target_base_url=parse.urljoin(f"{self._repo_url}/", "targets/"),
128120
target_dir=str(self._targets_dir),
129121
config=UpdaterConfig(app_user_agent=f"sigstore-python/{__version__}"),
122+
bootstrap=root_json,
130123
)
131124
try:
132125
self._updater.refresh()

test/unit/conftest.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
detect_credential,
3232
)
3333
from tuf.api.exceptions import DownloadHTTPError
34-
from tuf.ngclient import FetcherInterface
35-
from tuf.ngclient.updater import requests_fetcher
34+
from tuf.ngclient import FetcherInterface, updater
3635

3736
from sigstore._internal import tuf
3837
from sigstore._internal.rekor import _hashedrekord_from_parts
@@ -157,9 +156,7 @@ def _fetch(self, url: str) -> Iterator[bytes]:
157156
failure[filename] += 1
158157
raise DownloadHTTPError("File not found", 404)
159158

160-
monkeypatch.setattr(
161-
requests_fetcher, "RequestsFetcher", lambda app_user_agent: MockFetcher()
162-
)
159+
monkeypatch.setattr(updater, "Urllib3Fetcher", lambda app_user_agent: MockFetcher())
163160

164161
return success, failure
165162

test/unit/internal/test_trust.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ def test_trust_root_tuf_caches_and_requests(mock_staging_tuf, tuf_dirs):
8080

8181
trust_root = TrustedRoot.staging()
8282
# metadata was "downloaded" from staging
83-
expected = ["root.json", "snapshot.json", "targets.json", "timestamp.json"]
83+
expected = [
84+
"root.json",
85+
"root_history",
86+
"snapshot.json",
87+
"targets.json",
88+
"timestamp.json",
89+
]
8490
assert sorted(os.listdir(data_dir)) == expected
8591

8692
# Expect requests of top-level metadata (and 404 for the next root version)
@@ -126,9 +132,8 @@ def test_trust_root_tuf_offline(mock_staging_tuf, tuf_dirs):
126132

127133
trust_root = TrustedRoot.staging(offline=True)
128134

129-
# Only the embedded root is in local TUF metadata, nothing is downloaded
130-
expected = ["root.json"]
131-
assert sorted(os.listdir(data_dir)) == expected
135+
# local TUF metadata is not initialized, nothing is downloaded
136+
assert not os.path.exists(data_dir)
132137
assert reqs == {}
133138
assert fail_reqs == {}
134139

0 commit comments

Comments
 (0)