-
Notifications
You must be signed in to change notification settings - Fork 281
Fix 736: Rebuild roledb in refresh() even if root unchanged #737
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
In order to avoid freezes if role info is deleted due to prior validation failures, make sure that roledb is rebuilt during client tuf.client.updater.refresh(), even if root did not need to be updated. See Issue 736 for more details. Signed-off-by: Sebastien Awwad <[email protected]>
|
The relocation of the call to Note: Travis failed, so we probably need to update 1 or 2 test conditions. |
|
@awwad I'd like to include this important fix in our next scheduled release, which is approaching soon. Is it okay if I resolve the Travis/Appveyor failures and finish this pull request? |
|
Sure
…On Fri, Jun 8, 2018 at 08:26 Vladimir Diaz ***@***.***> wrote:
@awwad <https://github.com/awwad> I'd like to include this important fix
in our next scheduled release, which is approaching soon.
Is it okay if I resolve the Travis/Appveyor failures and finish this pull
request?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#737 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AMpkOG2T3vVJrlomMS9THevGpPyalHc6ks5t6m15gaJpZM4UT9bT>
.
|
Also document the assumption that the metadata store is the latest and exists in _update_metadata() Signed-off-by: Vladimir Diaz <[email protected]>
…adata in refresh() Signed-off-by: Vladimir Diaz <[email protected]>
Signed-off-by: Vladimir Diaz <[email protected]>
…ater.py Signed-off-by: Vladimir Diaz <[email protected]>
Signed-off-by: Vladimir Diaz <[email protected]>
Signed-off-by: Vladimir Diaz <[email protected]>
Signed-off-by: Vladimir Diaz <[email protected]>
|
@awwad I went ahead and (1) added a test condition for the persistent freeze attack (2) wrapped the line in I think the pull request now just needs to re-sync with the develop branch. Thanks for reporting the issue and submitting the initial fix! |
|
@trishankatdatadog |
awwad
left a 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 but for a comment improvement and two questions.
| # expired Snapshot and the locally trusted one, which should now be out of | ||
| # date. After the attack, attempt to re-issue a valid Snapshot to verify | ||
| # that the client is able to recover from the indefinite freeze attack via | ||
| # the snapshot metadata. |
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 it will be a bit confusing to future readers to refer to this as an indefinite freeze attack here without context (since there is nothing that obviously represents an attack in the test below). Perhaps:
# Serve the client expired Snapshot. The client should reject the given,
# expired Snapshot and the locally trusted one, which should now be out of
# date.
# After the attack, attempt to re-issue a valid Snapshot to verify that
# the client is still able to update. (A bug previously caused snapshot
# expiration or replay to result in an indefinite freeze.)You could also point to the particular issue, #736, in the comment, though that's probably less important. If that looks good, I can add the commit.
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 like the comment that you added, but we should also point to #736 so the reader can understand how the bug was caused.
I'd appreciate you adding the commit, if you are not busy.
| sorted(self.repository_updater.metadata['current'])) | ||
|
|
||
|
|
||
|
|
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.
Test looks good.
| self.assertEqual(sorted(['role1', 'root', 'snapshot', 'targets', 'timestamp']), | ||
| self.assertEqual(sorted(['root', 'snapshot', 'targets', 'timestamp']), | ||
| sorted(tuf.roledb.get_rolenames('test_repository1'))) | ||
| self.assertEqual(sorted(['role1', 'root', 'snapshot', 'targets', 'timestamp']), |
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 confused by this change. How did this result from the PR?
Edit: ah, probably from the targets_of_role change...?
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.
refresh() rebuilds the roledb and only refreshes top-level metadata. See line 212.
| securesystemslib.formats.RELPATH_SCHEMA.check_match(rolename) | ||
|
|
||
| self._refresh_targets_metadata(refresh_all_delegated_roles=True) | ||
|
|
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.
Why is refresh_all_delegated_roles necessary? This could be quite a few roles.
Next point is a bit complex:
targets_of_role remains a strange function to me if called on anything other than the Targets role itself. If the indicated role is a delegated role, it just isn't clear what it means to obtain trustworthy target info for whatever files are listed by a trustworthy version of that role. (Whose word are we taking on the latter?)
Perhaps the best we can do is to: obtain some not-validated or partially-validated version of the delegated role (because delegation pathways depend on file paths and we haven't specified one), get the list of targets specified by that not-validated role file, and then properly obtain trustworthy target info for those file paths (whether or not they are ultimately provided by the same role?).
This more complex point plays into the correct way to run targets_of_role on a delegated role.
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.
My thinking is that all_targets() and targets_of_roles() should be for clients that do not know ahead of time which targets are available on the repo, or provided by a particular role.
Community repos will certainly use get_one_valid_targetinfo(), but we might want to provide all_targets() and targets_of_roles() for simpler use cases / adopters.
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.
After an offline discussion, @awwad and I came to the conclusion that it's better to not support all_targets() and targets_of_role(). We'll open a separate issue to remove these two functions.
|
Does this break backwards-compatibility? |
I don't think this pull request breaks backwards-compatibility. @awwad Can you confirm? The change makes sure that the client has the latest metadata loaded into memory after a updater.refresh(), even if one of the top-level metadata hasn't been updated by the repository. |
|
No, I can't think of how it would break backward compatibility. (If it causes a problem, of course, LMK.) BTW, @trishankatdatadog, do you use |
to indicate the source of the freeze issue Signed-off-by: Sebastien Awwad <[email protected]>
|
(And from there, it looks like you get target info via get_one_valid_targetinfo) Okay, good. (: |
|
Thanks for checking and verifying, @awwad, much appreciated 🙇 |
|
Hi, any idea when v0.12.dev1 will be released on PyPI for testing? Thanks! |
|
I can do it sometime today, will keep you posted here. |
|
@trishankatdatadog |
|
I'll test it, thanks! |
In order to avoid freezes if role info is deleted due to prior
validation failures, make sure that roledb is rebuilt during
client tuf.client.updater.refresh(), even if root did not need
to be updated.
WIP: I may want to add some tests and wrap a line.
See Issue 736 for more details.
Fixes issue #736
Please verify and check that the pull request fulfills the following
requirements: