-
Notifications
You must be signed in to change notification settings - Fork 270
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
Enforce role name uniqueness and add Targets key helpers #1537
Enforce role name uniqueness and add Targets key helpers #1537
Conversation
6709675
to
355c3e1
Compare
355c3e1
to
90e4e5b
Compare
This is true. The argument against is that
|
Hmm yes, you are right about that. We don't want to make our users know each of the helper classes. |
90e4e5b
to
ba09c66
Compare
ba09c66
to
cd466cf
Compare
Inspired by #1553 commit "tests: Improve add_key/remove_key API tests" I added additional commit testing |
b760b07
to
c07ab06
Compare
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.
Then, if the key helper functions are used in Targets, then at least shouldn't we use more clarifying names for them?
If you callTargets.add_key()
then where are we adding this key? Yes, there is function documentation, but wonder if
names likeadd_delegated_key()
andremove_delegated_key()
(which are both a lot longer :( ) will be better?
I don't think Targets.add_key() is a bad name. If the reader is confused about delegators and delegated roles we likely aren't going to fix that with function names: they could misread your suggestion the same way "oh Targets.add_delegated_key()! this is the function I use to add the key that delegates from root to targets"
I can't say I am a fan of |
c07ab06
to
c37a63d
Compare
Pull Request Test Coverage Report for Build 1238606182Warning: 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 |
c37a63d
to
b413b16
Compare
I rebased on top of develop and had to resolve a couple of conflicts.
I was wondering what should we do if somebody calls |
fb22643
to
886c5d3
Compare
Now as you said it makes sense to warn the user that nothing happened when calling |
I'm afraid someone may have a different opinion on this one :D @jku |
I think in the future I'd suggest not combining issues like these two: If this had been two separate PRs it would have meant a bit more work for you (to rebase the second PR and to figure out when to put the second PR to review) but it would have meant reviewers need less context, can do faster reviews and the first PR would land faster. |
tuf/api/metadata.py
Outdated
raise exceptions.RoleAlreadyExistsError( | ||
f"Delegated role names must be unique! Got {new_role.name}" | ||
) |
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 is code that gets called from serialization (which wraps it in a catch all try-except) so using custom exceptions seems not useful.
repository code that wants to add roles is now going to use targets.delegation.roles[role.name] = role
so the exception won't be useful in that case either, as far as I can see...
We might want to provide some ways to easily order the dict at some point... but even then I don't see when a custom error would be useful
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.
Okay, will change the exception to ValueError
and will shorten the message.
Yes, I guess you are right. I thought I can combine fixing those two issues and that you will have the context given that |
886c5d3
to
9f5327c
Compare
key store. | ||
|
||
Raises: | ||
ValueError: If there are no delegated roles or if 'role' is not |
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.
How did we end up with two equivalent functions throwing ValueError
and KeyError
for the same thing. I am not sure about this.
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.
Now as you highlighted it, it's not great we throw two different types of exceptions for Root.remove_key()
- KeyError
and Targets.remove_key()
- ValueError
.
IMO the correct exception here should be ValueError
as the problems are in the given values -role
doesn't exist or keyid
doesn't point to a key used by that role.
@jku and @sechkova if you both agree I can change the Targets.remove_key()
exception to be ValueError
as well.
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.
(EDIT: this is a response to your comment, see context in the discussion)
I suppose you mean change Targets.add_key() exception: sounds good to me. ValueError is no doubt the correct error (but it mostly matters for aesthetics: this is a programmer error not an error that will be handled)
btw: you don't need to say "If there are no delegated roles" in the docstring: that is an implementation detail the caller does not need to know: for them the error is "'role' is not delegated by this Targets"
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 made an API change to Root.add_key()
and Root.remove_key()
so that they throw ValueError
instead of KeyError
on wrong given arguments.
The reason for this change is that ValueError
in my opinion is the right exception that should be thrown when the value is not correct and I think it's important to be consistent when calling delegator.add_key
or delegator.remove_keyno matter if the delegator is
Rootor
Targets`.
9f5327c
to
496ab2b
Compare
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.
Looks good, left some style comments: probably none of them absolutely necessary.
key store. | ||
|
||
Raises: | ||
ValueError: If there are no delegated roles or if 'role' is not |
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.
(EDIT: this is a response to your comment, see context in the discussion)
I suppose you mean change Targets.add_key() exception: sounds good to me. ValueError is no doubt the correct error (but it mostly matters for aesthetics: this is a programmer error not an error that will be handled)
btw: you don't need to say "If there are no delegated roles" in the docstring: that is an implementation detail the caller does not need to know: for them the error is "'role' is not delegated by this Targets"
7ba9dd4
to
a25cab9
Compare
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.
Looks ok, still have two comments on the errors though.
I'm fine with the API change (KeyError -> ValueError) even if I usually would be against changing API with no practical benefit: the errors in question are IMO clear programming mistakes so we don't expect there to exist code that might break if we change the errors, but more consistent errors should be useful to developers making the programming mistake.
If you can rebase as well that would be great (the workflow jobs changed name and branch protection will now think you haven't passed the tests) |
85fb461
to
0e7dac3
Compare
0e7dac3
to
07a18ba
Compare
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 think this is a correct change, thanks.
Commit messages do not make clear that the Delegations API has a breaking change, we should get better at this as we can't expect the release notes writer to always make the connection... Anyway LGTM: we can mention API change in the merge commit maybe?
The spec does not say anything about role name uniqueness in a delegations object, but I believe we cannot safely allow multiple roles with the same role name in the roles array of a delegations object. If we did then the roles could have different keyids, and then we would end up in a situation where metadata may be both a valid delegation and an invalid delegation at the same time, depending on how the role gets chosen and that does not seem like the intention of the design. There is an issue open in the specification with number 167 about that issue. Regardless of the Metadata API, I think we should enforce role name uniqueness. I chose to change the data structure containing roles to OrderedDict, where keys are role names and values are DelegatedRole instances. This made sense to me as role names are the unique identifier of a role and their order is important to the way they are traversed afterward. Note: we can't use OrderedDict as type annotation until we drop support for Python 3.6: https://docs.python.org/3/library/typing.html#typing.OrderedDict That's why I used quotes around "OrderedDict" annotation, because I can't import it. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
Move the Delegation class serialization tests from "test_api.py" to test_metadata_serialization.py module focused on serialization testing. Additionally, a test for empty keys and roles will be added in my upcomming pr theupdateframework#1511. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
We can remove the conditional imports from tests as now we support python versions 3.6+. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
Root class has the functionality to add and remove keys for delegated metadata (add_key()/remove_key()) but the other delegator Targets does not. It should provide the same/similar functionality. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
This is an API change to the exceptions thrown in Root.add_key() and Root.remove_key(). The reason for that change is that in my opinion the correct exceptions in these cases should be "ValueError" instead of "KeyError" as the problems are in the given values - role doesn't exist or key is not used by a particular role. Additionally, document the thrown exceptions in "Root.add_key" and add a test which invokes that exception. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
07a18ba
to
f00295f
Compare
Now it should be clearer and I am not sure what will be the value in adding a note about the API changes anymore. |
Fixes #1426, #1469
Description of the changes being introduced by the pull request:
This pr contains three types of changes:
Enforce Delegation role name uniqueness
The spec does not say anything about role name uniqueness in a
delegations object, but I believe we cannot safely allow multiple roles
with the same role name in the roles array of a delegations object.
If we did then the roles could have different keyids, and then we would
end up in a situation where metadata may be both a valid delegation
and an invalid delegation at the same time, depending on how the role
gets chosen and that does not seem like the intention of the design.
There is an issue open in the specification with number 167 about
that issue.
Regardless of the Metadata API, I think we should enforce role name
uniqueness.
I chose to change the data structure containing roles to
OrderedDict, where keys are role names and values, are DelegatedRole
instances, because role names are the unique identifier of a role and
their order is important to the way they are traversed afterward.
Add missing key helpers in Delegations
Root class has the functionality to add and remove keys for delegated
metadata (add_key()/remove_key()) but the other delegator Targets does
not.
It should provide the same/similar functionality.
Some cleaning
test_metadata_serialization.py
Please verify and check that the pull request fulfills the following
requirements: