-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use TUF to download key/cert material #351
Conversation
TrustUpdater can be used to fetch specific trust roots: * Currently supports fetching * ctfe keys and * the rekor key * Caches target files in ~/.cache/sigstore-python/ * Stores metadata in ~/.local/share/sigstore-python/ * Expects to either * find the metadata _for the given URL_ in metadata store * (for prod and stage only) find the boostrap root.json in sigstore/_store The "API" that TrustUpdater provides is not meant to be final: it is the minimal one that should fulfill current needs. Nothing uses the TrustUpdater yet, but it's testable: >>> from sigstore._tuf import TrustUpdater, DEFAULT_TUF_URL >>> updater = TrustUpdater(DEFAULT_TUF_URL) >>> rekor_key_bytes = updater.get_rekor_key() Co-authored-by: Joshua Lock <[email protected]> Co-authored-by: wxjdsr <[email protected]> Signed-off-by: Jussi Kukkonen <[email protected]>
CTKeyring: * Take bytes as constructore input: this makes it easier to feed things from either CLI arguments or the TUF trust updater. * Remove tests that no longer make sense. The prod/staging contant should still be tested but TUF is now used in the same flows: Unsure how to best test this. Use TUF to find the CTFE and rekor key when using "production" or "staging". Note that "staging" is currently untested: I am not sure even the URL makes sense. Signed-off-by: Jussi Kukkonen <[email protected]> Signed-off-by: Jussi Kukkonen <[email protected]>
Use TUF to get CTFE/Rekor keys in the non-staging, non-production flow. As before, the assumption is that user wants production keys in this case. Refactor TrustUpdater so that it does not do network traffic if nothing is requested. Signed-off-by: Jussi Kukkonen <[email protected]>
Signed-off-by: Jussi Kukkonen <[email protected]>
* Assume that the active fulcio certs in the repository form a certificate chain that cryptography can ingest * Refactor RekorClient construction so that we avoid constructing multiple TrustTupdaters Signed-off-by: Jussi Kukkonen <[email protected]>
If this is not production or staging but rekor key is not given, use production: this is what original (non-tuf) code was doing as well. Signed-off-by: Jussi Kukkonen <[email protected]>
https://tuf-root-staging.storage.googleapis.com/ does work as staging repository. There is still a bug somewhere as staging verify currently fails. Signed-off-by: Jussi Kukkonen <[email protected]>
This is needed to bootstrap the TUF metadata with --staging. Signed-off-by: Jussi Kukkonen <[email protected]>
Oh, a note on fulcio: I now feed all certs with usage "Fulcio" and status "Active" to Verifier with the assumption that
hopefully there are no problems with these assumptions |
@asraa if you want to have a look at the |
These assumptions should be fine! We throw everything into an OpenSSL X.509 store, and I don't believe it imposes any order of insertion. |
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Online tests now pass, but the forced offline tests are still failing (as expected). |
IMO this is worth an upstream PR -- looks like most of these should really be Edit: Opened: theupdateframework/python-tuf#2243 |
* Bring back RekorClient.production() and RekorClient.staging(): these are simple but make the calling code slightly clearer maybe * Add a TrustUpdater argument to those methods: if you use production/staging, you need a TrustUpdater * The TrustUpdater can not be constructed inside RekorClient as other components may need it as well. It's not perfectly elegant for the caller but it's not horrible either: updater = TrustUpdater.staging() client = RekorClient.staging(updater) This design means TrustUpdater does not know anything about the sigstore mechanisms: it just discovers and downloads files. Signed-off-by: Jussi Kukkonen <[email protected]>
Signed-off-by: Jussi Kukkonen <[email protected]>
No functional change, just refactor the target discovery into a single method. Signed-off-by: Jussi Kukkonen <[email protected]>
The test doesn't make a lot of sense now that the keys are not being read from the _store. Signed-off-by: Jussi Kukkonen <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Annoying. Signed-off-by: William Woodruff <[email protected]>
This is looking pretty good to me! I think we can move it out of a draft for now; there are only a few small cleanup tasks that I think should get done before we merge. |
Signed-off-by: Alex Cameron <[email protected]>
I'm seeing some weird lint errors on this branch that I don't see in
Looks like that file hasn't even been touched. |
This is unrelated, it's not showing up in main because William added an ignore in 0647d75. |
I assumed that was necessary somehow because we switched to Ruff, but your branch doesn't have that commit. Anyway, if you don't mind, I'll merge in |
Signed-off-by: Alex Cameron <[email protected]>
Signed-off-by: Jussi Kukkonen <[email protected]>
Signed-off-by: Jussi Kukkonen <[email protected]>
This is a potential improvement, not a necessary one. Signed-off-by: Jussi Kukkonen <[email protected]>
I pushed some tiny documentation tweaks but I would agree: this looks good to me apart from the final linting issue #351 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM provided that the linting is sorted out. Nice work.
Also tweak one annotation (remove unneeded quotes) Signed-off-by: Jussi Kukkonen <[email protected]>
I added the "#nosec" to get tests passing: feel free to solve the issue in some other way if you want. |
/gcbrun |
Signed-off-by: William Woodruff <[email protected]>
/gcbrun |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
||
# NOTE: _updater has been fully initialized at this point, but mypy can't see that. | ||
targets = self._updater._trusted_set.targets.signed.targets # type: ignore[union-attr] | ||
for target_info in targets.values(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually would caution against using the custom metadata and use the path filters "rekor*", "fulcio*", "ctfe*", instead as the filtering mechanism. While we'll keep some of the metadata, I think we are aiming to change them (for example, status will be deprecated in favor of explicit NotBefore/NotAfter ranges)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That being said "usage" should match here and be stable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I knew the custom metadata was not a permanent solution but I'm not sure filtering by path is going to be either -- maybe makes sense to update once the target discovery and delegation plans are properly decided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure filtering by path is going to be either -- maybe makes sense to update once the target discovery and delegation plans are properly decided
That's fair! Yeah, in the end distributing as a single bundle would probably fix that and that likely will be the case next year. The migration to that will be slow anyway (as in, the existing targets will continue to be distributed like this).
Should fix #25 by using TUF to download all certs and keys. It is based on code by @joshuagl, @wxjdsr (co-authors on first commit in this branch) but it is a significant rewrite compared to their branches.
FYI also @woodruffw, @di, @SantiagoTorres.
I'm allowing edits by maintainers, go wild if you feel like it.
Status (updated dec 22):
Some TODO items (there are certainly more)
~/.local/share/sigstore-python/tuf/<url>/
and targets are cached in~/.cache/sigstore-python/tuf/<url>/
-- this is not great for windows