-
Notifications
You must be signed in to change notification settings - Fork 278
Repository module and example #2193
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
Conversation
Pull Request Test Coverage Report for Build 3697521735Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Forgot to mention: you may be tempted to run the server and use a browser to see the metadata being served. This sort of works but ultimately breaks things as at least Chrome does things that are incompatible with single thread servers like |
Having played with this for about a week now, I think there is one "Repository implementation" we may want to include in the library itself. While the repositories themselves may be wildly different, the "developer tools" or "signing tools" are probably very similar:
So the result should be a mix of ngclient.Updater and the SimpleRepository from this PR. This is clearly future work and will not happen in in this PR, I'm just writing the idea out there. |
I plan to add another repository example as well. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Plan for tuf.repository is: * provides useful functionality for TUF repository-side implementations (repository applications, developer tools, etc) * is minimalistic: only features that most implementations will use should be icluded * Only example implementations will be provided in python-tuf * As more repository implementations are built using tuf.repository we can evaluate what extended functionality is useful In this PR, a single abstract class is added that provides a framework for building repository-modifying tools. In subsequent commits some examples will be added that demonstrate how to use the class. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
This uses the repository module to create an app that * generates everything from scratch * serves metadata and targets from memory * simulates a live repository by adding new targets every few seconds Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
* Support any repository (that serves /targets/ and /metadata/) with --url * Support multiple repositories by aking the local cache repository-specific * Add "tofu" command to initialize with Trust-On-First-Use * Update README so it uses the new repository application example Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
plain rebase, no changes |
A potential change to snapshot/timestamp:
I think this would be as flexible but would make calling snapshot()/timestamp() easier EDIT: I've implemented this in later commit |
This does not make the examples simpler now, but it will when there are multiple locations where snapshot/timestamp are called. * This way the snapshot/timestamp input material is an internal detail of Repository and the call sites will be simpler. * Both methods now have a "force" argument that can be used to create a new version regardless of meta info changes * but implementations are now required to implement snapshot_info and targets_infos properties that represent the current snapshot and targets versions in the repository Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Otherwise the metafile cache and the metadata object end up pointing to same instances which starts breaking later. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
This is not required for the demo but is more realistic: we keep a cache of targets versions so that we can produce a new snapshot whenever one is needed, without accessing all of the targets metadata to do so. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Tweak comments as well Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
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.
Impressive work! I've given this a very close look, especially tuf/repository
and examples/repository/_simplerepo.py
, and only found some minor nits. I think we can get this merged and even released soon, but maybe note somewhere that this is more experimental than ngclient and metadata api.
examples/repository/_simplerepo.py
Outdated
|
||
Attributes: | ||
role_cache: Contains every historical metadata version of every role in | ||
this repositorys. Keys are rolenames and values are lists of |
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.
this repositorys. Keys are rolenames and values are lists of | |
this repository. Keys are role names and values are lists of |
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.
Ping s/repositorys/repository
This is a collection of comment, documentation and logging fixes. The noteworthy part is making it clear that repository is not stable API yet: I think this is a good idea. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
(I can't believe I'm asking for bikeshedding but here goes...) One thing that I would like bring up for discussion is naming:
Another thing is the idea of the |
tuf/repository/_repository.py
Outdated
def edit( | ||
self, role: str, init: bool = False | ||
) -> Generator[Signed, None, None]: |
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.
the core usability complaint I have with edit() is that it doesn't handle better static typing:
with edit("targets") as targets:
# mypy sees targets as type Signed, not Targets
Most issues would just be solved by adding a typed helper:
def edit_targets(
self, role: str, init: bool = False
) -> Generator[Targets, None, None]:
(not sure if the other types even need a helper: timestamp and snapshot at least don't need so much editing: Repository handles the usual cases already)
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 am not very exited about adding a helper just for typing. What's the implication if mypy doesn't know the subtype?
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.
The implication is that more complex code in the with-block (like this attempt at easy target removal) won't have type suggestions in your editor and won't be type checked by mypy unless you do some extra work.
The workaround I use in that example makes VSCode suggestions work but doesn't make mypy happy... I think the least disruptive workaround is probably a assert(isinstance(Targets, targets))
as the first line inside the with-block.
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.
but just to be clear: I'm not suggesting to add a helper in this PR -- just bringing up potential areas of improvement
Fair. Naming is important, and hard.
I had similar thoughts. These names do have other connotations. What about more abstract terms, like start/end, enter/exit, pre_edit/post_edit? ... otoh, those make less sense, when used outside of edit. Maybe open/close are just fine.
Can't think of better names. Let's solve this with documentation. Maybe add a note to look at For that it might be helpful to rename the second return value in snapshot (e.g. to Btw., it also took me a bit to understand the magical defaultdict+lambda -powered assignment in SimpleRepository, when I tried to understand
I think it does. One thing I was wondering was whether open/close arguments should also be left unspecified given that open and close can be anything the implementer wants them to be. E.g. they could both accept
I think it's fine. |
Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
yeah, that defaultdict is likely only useful once in in close() ... so the case of missing key could be handled manually there. But on the other hand role_cache and signer_cache use the same mechanism (it would even look the same if MetaFile() had a default version value). I'll just add a comment |
Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
I've kept the names but I tweaked the docstring of the methods to make it clear that the returned values are metadata versions that are no longer part of snapshot/timestamp meta. I think I've now addressed everything so far. |
From chat with lukas:
this does not really need the init argument... could also move sign() out of the ABC -- then close also does not need the sign_only argument. |
This no longer seems needed: if the metadata store does not contain a single version of role, then open() can assume it is initializing. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
This is only needed for threshold signing and not even used in the example: leave it to the implementations to handle for now. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Two changes:
|
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.
Please fix two typos and one outdated docstring and this is good to go.
Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
Calling this a repository module sounds a little too grand (it's literally an abstract class that does almost nothing)... but I think it works so maybe we start with this.
I'm adding some reviewers for visibility. If someone wants to see what it does:
Note that the Repository class is just a "ergonomic metadata editing framework" -- it makes producing valid and logical next versions of TUF metadata within a repository easier. So it's not really a "repository" (module name makes sense as this is for repository side tooling but the class name could still be debated)
examples/repository should also be extended (or other examples added):
Fixes #1136 maybe?