Skip to content

Commit 7ba8a25

Browse files
tnytownwoodruffw
andauthored
tuf: embed trusted root target (#611)
* tuf: embed trusted root target Signed-off-by: Andrew Pan <[email protected]> * CHANGELOG: blurb Signed-off-by: Andrew Pan <[email protected]> * errors: doc `RootError.diagnostics` Signed-off-by: Andrew Pan <[email protected]> * tuf: check that root does not exist before writing Signed-off-by: Andrew Pan <[email protected]> * CHANGELOG: reformat Signed-off-by: Andrew Pan <[email protected]> * test_tuf: do not expect 2.root.json The new version of the root file should have been downloaded and persisted from the remote by the last TrustUpdater instance. Signed-off-by: Andrew Pan <[email protected]> * CHANGELOG: reflow Signed-off-by: William Woodruff <[email protected]> --------- Signed-off-by: Andrew Pan <[email protected]> Signed-off-by: William Woodruff <[email protected]> Co-authored-by: William Woodruff <[email protected]>
1 parent 1d20c6c commit 7ba8a25

File tree

11 files changed

+257
-53
lines changed

11 files changed

+257
-53
lines changed

Diff for: CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ All versions prior to 0.9.0 are untracked.
88

99
## [Unreleased]
1010

11+
### Changed
12+
13+
* A cached copy of the trust bundle is now included with the distribution.
14+
([#611](https://github.com/sigstore/sigstore-python/pull/611))
15+
1116
## [1.1.2]
1217

1318
### Fixed
1419

1520
* Updated the `staging-root.json` for recent changes to the Sigstore staging
1621
instance ([#602](https://github.com/sigstore/sigstore-python/pull/602))
22+
1723
* Switched TUF requests to their CDN endpoints, rather than direct GCS
1824
access ([#609](https://github.com/sigstore/sigstore-python/pull/609))
1925

@@ -27,18 +33,22 @@ All versions prior to 0.9.0 are untracked.
2733
generate staging and production OIDC tokens, which are used to test the
2834
`sigstore.sign` module. All signing tests need to be completed before token
2935
expiry, which is currently 60 seconds after issuance.
36+
3037
* Network-related errors from the `sigstore._internal.tuf` module now have better
3138
diagnostics.
3239

3340
### Changed
3441

3542
* Replaced ambient credential detection logic with the `id` package
3643
([#535](https://github.com/sigstore/sigstore-python/pull/535))
44+
3745
* Revamped error diagnostics reporting. All errors with diagnostics now implement
3846
`sigstore.errors.Error`.
47+
3948
* Trust root materials are now retrieved from a single trust bundle,
4049
if it is available via TUF
4150
([#542](https://github.com/sigstore/sigstore-python/pull/542))
51+
4252
* Improved diagnostics around Signed Certificate Timestamp verification failures.
4353
([#555](https://github.com/sigstore/sigstore-python/pull/555))
4454

Diff for: sigstore/_internal/tuf.py

+26-13
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from tuf.ngclient import RequestsFetcher, Updater
4343

4444
from sigstore._utils import read_embedded
45-
from sigstore.errors import MetadataError, TUFError
45+
from sigstore.errors import MetadataError, RootError, TUFError
4646

4747
logger = logging.getLogger(__name__)
4848

@@ -121,24 +121,37 @@ def __init__(self, url: str) -> None:
121121
self._repo_url = url
122122
self._metadata_dir, self._targets_dir = _get_dirs(url)
123123

124+
rsrc_prefix: str
125+
if self._repo_url == DEFAULT_TUF_URL:
126+
rsrc_prefix = "prod"
127+
elif self._repo_url == STAGING_TUF_URL:
128+
rsrc_prefix = "staging"
129+
else:
130+
raise RootError
131+
124132
# Initialize metadata dir
133+
self._metadata_dir.mkdir(parents=True, exist_ok=True)
125134
tuf_root = self._metadata_dir / "root.json"
135+
126136
if not tuf_root.exists():
127-
if self._repo_url == DEFAULT_TUF_URL:
128-
fname = "root.json"
129-
elif self._repo_url == STAGING_TUF_URL:
130-
fname = "staging-root.json"
131-
else:
132-
raise Exception(f"TUF root not found in {tuf_root}")
133-
134-
self._metadata_dir.mkdir(parents=True, exist_ok=True)
135-
root_json = read_embedded(fname)
136-
with tuf_root.open("wb") as io:
137-
io.write(root_json)
137+
try:
138+
root_json = read_embedded("root.json", rsrc_prefix)
139+
except FileNotFoundError as e:
140+
raise RootError from e
141+
142+
tuf_root.write_bytes(root_json)
138143

139144
# Initialize targets cache dir
140-
# NOTE: Could prime the cache here with any embedded certs/keys
141145
self._targets_dir.mkdir(parents=True, exist_ok=True)
146+
trusted_root_target = self._targets_dir / "trusted_root.json"
147+
148+
if not trusted_root_target.exists():
149+
try:
150+
trusted_root_json = read_embedded("trusted_root.json", rsrc_prefix)
151+
except FileNotFoundError as e:
152+
raise RootError from e
153+
154+
trusted_root_target.write_bytes(trusted_root_json)
142155

143156
logger.debug(f"TUF metadata: {self._metadata_dir}")
144157
logger.debug(f"TUF targets cache: {self._targets_dir}")
File renamed without changes.

Diff for: sigstore/_store/prod/trusted_root.json

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{
2+
"mediaType": "application/vnd.dev.sigstore.trustedroot+json;version=0.1",
3+
"tlogs": [
4+
{
5+
"baseUrl": "https://rekor.sigstore.dev",
6+
"hashAlgorithm": "SHA2_256",
7+
"publicKey": {
8+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==",
9+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
10+
"validFor": {
11+
"start": "2021-01-12T11:53:27.000Z"
12+
}
13+
},
14+
"logId": {
15+
"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
16+
}
17+
}
18+
],
19+
"certificateAuthorities": [
20+
{
21+
"subject": {
22+
"organization": "sigstore.dev",
23+
"commonName": "sigstore"
24+
},
25+
"uri": "https://fulcio.sigstore.dev",
26+
"certChain": {
27+
"certificates": [
28+
{
29+
"rawBytes": "MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ=="
30+
}
31+
]
32+
},
33+
"validFor": {
34+
"start": "2021-03-07T03:20:29.000Z",
35+
"end": "2022-12-31T23:59:59.999Z"
36+
}
37+
},
38+
{
39+
"subject": {
40+
"organization": "sigstore.dev",
41+
"commonName": "sigstore"
42+
},
43+
"uri": "https://fulcio.sigstore.dev",
44+
"certChain": {
45+
"certificates": [
46+
{
47+
"rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ"
48+
},
49+
{
50+
"rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow="
51+
}
52+
]
53+
},
54+
"validFor": {
55+
"start": "2022-04-13T20:06:15.000Z"
56+
}
57+
}
58+
],
59+
"ctlogs": [
60+
{
61+
"baseUrl": "https://ctfe.sigstore.dev/test",
62+
"hashAlgorithm": "SHA2_256",
63+
"publicKey": {
64+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbfwR+RJudXscgRBRpKX1XFDy3PyudDxz/SfnRi1fT8ekpfBd2O1uoz7jr3Z8nKzxA69EUQ+eFCFI3zeubPWU7w==",
65+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
66+
"validFor": {
67+
"start": "2021-03-14T00:00:00.000Z",
68+
"end": "2022-10-31T23:59:59.999Z"
69+
}
70+
},
71+
"logId": {
72+
"keyId": "CGCS8ChS/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3I="
73+
}
74+
},
75+
{
76+
"baseUrl": "https://ctfe.sigstore.dev/2022",
77+
"hashAlgorithm": "SHA2_256",
78+
"publicKey": {
79+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiPSlFi0CmFTfEjCUqF9HuCEcYXNKAaYalIJmBZ8yyezPjTqhxrKBpMnaocVtLJBI1eM3uXnQzQGAJdJ4gs9Fyw==",
80+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
81+
"validFor": {
82+
"start": "2022-10-20T00:00:00.000Z"
83+
}
84+
},
85+
"logId": {
86+
"keyId": "3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4="
87+
}
88+
}
89+
],
90+
"timestampAuthorities": []
91+
}
File renamed without changes.

Diff for: sigstore/_store/staging/trusted_root.json

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{
2+
"mediaType": "application/vnd.dev.sigstore.trustedroot+json;version=0.1",
3+
"tlogs": [
4+
{
5+
"baseUrl": "https://rekor.sigstage.dev",
6+
"hashAlgorithm": "SHA2_256",
7+
"publicKey": {
8+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDODRU688UYGuy54mNUlaEBiQdTE9nYLr0lg6RXowI/QV/RE1azBn4Eg5/2uTOMbhB1/gfcHzijzFi9Tk+g1Prg==",
9+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
10+
"validFor": {
11+
"start": "2021-01-12T11:53:27.000Z"
12+
}
13+
},
14+
"logId": {
15+
"keyId": "0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY="
16+
}
17+
}
18+
],
19+
"certificateAuthorities": [
20+
{
21+
"subject": {
22+
"organization": "sigstore.dev",
23+
"commonName": "sigstore"
24+
},
25+
"uri": "https://fulcio.sigstage.dev",
26+
"certChain": {
27+
"certificates": [
28+
{
29+
"rawBytes": "MIIB9jCCAXugAwIBAgITDdEJvluliE0AzYaIE4jTMdnFTzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDMyNTE2NTA0NloXDTMyMDMyMjE2NTA0NVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMo9BUNk9QIYisYysC24+2OytoV72YiLonYcqR3yeVnYziPt7Xv++CYE8yoCTiwedUECCWKOcvQKRCJZb9ht4Hzy+VvBx36hK+C6sECCSR0x6pPSiz+cTk1f788ZjBlUZaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP9CMrpofas6cK/cDNQa4j6Hj2ZlMB8GA1UdIwQYMBaAFP9CMrpofas6cK/cDNQa4j6Hj2ZlMAoGCCqGSM49BAMDA2kAMGYCMQD+kojuzMwztNay9Ibzjuk//ZL5m6T2OCsm45l1lY004pcb984L926BowodoirFMcMCMQDIJtFHhP/1D3a+M3dAGomOb6O4CmTry3TTPbPsAFnv22YA0Y+P21NVoxKDjdu0tkw="
30+
},
31+
{
32+
"rawBytes": "MIICGTCCAaCgAwIBAgITJta/okfgHvjabGm1BOzuhrwA1TAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDQxNDIxMzg0MFoXDTMyMDMyMjE2NTA0NVowNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASosAySWJQ/tK5r8T5aHqavk0oI+BKQbnLLdmOMRXHQF/4Hx9KtNfpcdjH9hNKQSBxSlLFFN3tvFCco0qFBzWYwZtsYsBe1l91qYn/9VHFTaEVwYQWIJEEvrs0fvPuAqjajezB5MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRxhjCmFHxib/n31vQFGn9f/+tvrDAfBgNVHSMEGDAWgBT/QjK6aH2rOnCv3AzUGuI+h49mZTAKBggqhkjOPQQDAwNnADBkAjAM1lbKkcqQlE/UspMTbWNo1y2TaJ44tx3l/FJFceTSdDZ+0W1OHHeU4twie/lq8XgCMHQxgEv26xNNiAGyPXbkYgrDPvbOqp0UeWX4mJnLSrBr3aN/KX1SBrKQu220FmVL0Q=="
33+
}
34+
]
35+
},
36+
"validFor": {
37+
"start": "2022-03-25T16:50:46.000Z"
38+
}
39+
}
40+
],
41+
"ctlogs": [
42+
{
43+
"baseUrl": "https://ctfe.sigstage.dev/test",
44+
"hashAlgorithm": "SHA2_256",
45+
"publicKey": {
46+
"rawBytes": "MIICCgKCAgEA27A2MPQXm0I0v7/Ly5BIauDjRZF5Jor9vU+QheoE2UIIsZHcyYq3slHzSSHy2lLj1ZD2d91CtJ492ZXqnBmsr4TwZ9jQ05tW2mGIRI8u2DqN8LpuNYZGz/f9SZrjhQQmUttqWmtu3UoLfKz6NbNXUnoo+NhZFcFRLXJ8VporVhuiAmL7zqT53cXR3yQfFPCUDeGnRksnlhVIAJc3AHZZSHQJ8DEXMhh35TVv2nYhTI3rID7GwjXXw4ocz7RGDD37ky6p39Tl5NB71gT1eSqhZhGHEYHIPXraEBd5+3w9qIuLWlp5Ej/K6Mu4ELioXKCUimCbwy+Cs8UhHFlqcyg4AysOHJwIadXIa8LsY51jnVSGrGOEBZevopmQPNPtyfFY3dmXSS+6Z3RD2Gd6oDnNGJzpSyEk410Ag5uvNDfYzJLCWX9tU8lIxNwdFYmIwpd89HijyRyoGnoJ3entd63cvKfuuix5r+GHyKp1Xm1L5j5AWM6P+z0xigwkiXnt+adexAl1J9wdDxv/pUFEESRF4DG8DFGVtbdH6aR1A5/vD4krO4tC1QYUSeyL5Mvsw8WRqIFHcXtgybtxylljvNcGMV1KXQC8UFDmpGZVDSHx6v3e/BHMrZ7gjoCCfVMZ/cFcQi0W2AIHPYEMH/C95J2r4XbHMRdYXpovpOoT5Ca78gsCAwEAAQ==",
47+
"keyDetails": "PKCS1_RSA_PKCS1V5",
48+
"validFor": {
49+
"start": "2021-03-14T00:00:00.000Z"
50+
}
51+
},
52+
"logId": {
53+
"keyId": "s9AOb93xWxr+a4ztxJnxxJCX7VZ0V3IF4jTu/OoL84A="
54+
}
55+
},
56+
{
57+
"baseUrl": "https://ctfe.sigstage.dev/2022",
58+
"hashAlgorithm": "SHA2_256",
59+
"publicKey": {
60+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh99xuRi6slBFd8VUJoK/rLigy4bYeSYWO/fE6Br7r0D8NpMI94+A63LR/WvLxpUUGBpY8IJA3iU2telag5CRpA==",
61+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
62+
"validFor": {
63+
"start": "2022-07-01T00:00:00.000Z"
64+
}
65+
},
66+
"logId": {
67+
"keyId": "++JKOMQt7SJ3ynUHnCfnDhcKP8/58J4TueMqXuk3HmA="
68+
}
69+
},
70+
{
71+
"baseUrl": "https://ctfe.sigstage.dev/2022-2",
72+
"hashAlgorithm": "SHA2_256",
73+
"publicKey": {
74+
"rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8gEDKNme8AnXuPBgHjrtXdS6miHqc24CRblNEOFpiJRngeq8Ko73Y+K18yRYVf1DXD4AVLwvKyzdNdl5n0jUSQ==",
75+
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
76+
"validFor": {
77+
"start": "2022-07-01T00:00:00.000Z"
78+
}
79+
},
80+
"logId": {
81+
"keyId": "KzC83GiIyeLh2CYpXnQfSDkxlgLynDPLXkNA/rKshno="
82+
}
83+
}
84+
],
85+
"timestampAuthorities": []
86+
}

Diff for: sigstore/_utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ def sha256_streaming(io: IO[bytes]) -> bytes:
166166
return sha256.digest()
167167

168168

169-
def read_embedded(name: str) -> bytes:
169+
def read_embedded(name: str, prefix: str) -> bytes:
170170
"""
171171
Read a resource embedded in this distribution of sigstore-python,
172172
returning its contents as bytes.
173173
"""
174-
return resources.files("sigstore._store").joinpath(name).read_bytes() # type: ignore
174+
return resources.files("sigstore._store").joinpath(prefix, name).read_bytes() # type: ignore

Diff for: sigstore/errors.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def diagnostics(self) -> str:
6464
)
6565

6666
return (
67-
"""A network issue occurred.
67+
"""\
68+
A network issue occurred.
6869
6970
Check your internet connection and try again.
7071
"""
@@ -92,7 +93,8 @@ def diagnostics(self) -> str:
9293
"Please report this issue at <https://github.com/sigstore/sigstore-python/issues/new>.",
9394
)
9495

95-
return f"""{self.message}.
96+
return f"""\
97+
{self.message}.
9698
9799
{details}
98100
"""
@@ -104,3 +106,14 @@ class MetadataError(Error):
104106
def diagnostics(self) -> str:
105107
"""Returns diagnostics for the error."""
106108
return f"""{str(self)}."""
109+
110+
111+
class RootError(Error):
112+
"""Raised when TUF cannot establish its root of trust."""
113+
114+
def diagnostics(self) -> str:
115+
"""Returns diagnostics for the error."""
116+
return """\
117+
Unable to establish root of trust.
118+
119+
This error may occur when the resources embedded in this distribution of sigstore-python are out of date."""

Diff for: test/unit/conftest.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,12 @@ def mock_staging_tuf(monkeypatch, tuf_dirs):
192192
class MockFetcher(FetcherInterface):
193193
def _fetch(self, url: str) -> Iterator[bytes]:
194194
filepath = _TUF_ASSETS / urlparse(url).path.lstrip("/")
195+
filename = filepath.name
195196
if filepath.is_file():
196-
success[filepath] += 1
197+
success[filename] += 1
197198
return BytesIO(filepath.read_bytes())
198199

199-
failure[filepath] += 1
200+
failure[filename] += 1
200201
raise DownloadHTTPError("File not found", 404)
201202

202203
monkeypatch.setattr(tuf, "_get_fetcher", lambda: MockFetcher())

0 commit comments

Comments
 (0)