-
Notifications
You must be signed in to change notification settings - Fork 275
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
Relying on mandatory DelegatedRole.name attribute when TAP 15 describes it as optional #1943
Comments
Yes, we definitely still need distinct names for each "bin-n" role, otherwise the client can't download the targets metadata needed for a target in a bin. The challenge with TAP 15 is that the delegating targets metadata does not list all its delegatees anymore, but rather a number ( Currently, the idea is to compute the name for each bin using a configured prefix |
The problem is that it's possible to have |
I think the problem is that |
Yes, you are correct!
This means that |
The idea that a delegations dictionary that contains a succinct delegation can only contain that delegation and no others seems reasonable but I don't think it comes from TAP 15? Note that I'm not opposed to making implementation restrictions, just want to be clear when we do those. A quick unfinished alternative idea: Internally use special DelegatedRole.name = "" for succinct delegation (and prevent that being otherwise used). This would change the requirement to "delegations dictionary can contain a maximum of one succinct delegation but could contain other normal delegations: these can be ordered by normal means". |
Yet more alternatives: use the first bin-n-name as the roles dictionary key
This dictionary key would obviously be just an implementation detail: the serialized format would be as described in tap15 |
You are correct! I assumed only DelegatedRole could exist when
you see that after the delegated role describing the succinct hash information there is
I think I prefer this idea more than the one with the usage of
I am not sure you will ever need to use multiple succinct hash delegations.
Still, if we decide to use bin-name how do you imagine this to happen? |
That is indeed valid feedback for the TAP itself... even combining normal delegations and succinct ones feels quite weird. But strictly speaking the format in the TAP is currently designed to allow multiple succinct delegations so we'll have to at least document this diversion if we implement it that way. @mnm678 maybe has an opinion on combining a succinct delegation with either another succinct delegation or normal delegations -- what was the TAP intention here? |
I wanted to make one thing clear:
so one option is that python-tuf keeps requiring a role name and we suggest a modification to the TAP. |
I think it makes sense that I would love to hear @mnm678 about that. |
This is a great discussion!
The TAP purposefully left the option for multiple succinct delegations, as at the time I didn't see the need to restrict this. There may be a case when a repository would have multiple succinct delegations signed by different keys (especially a large repository like DockerHub). But if this is a sticking point for the implementation, I don't think it's very important and it hasn't specifically been requested. @trishankatdatadog has some of the real-world use cases for this TAP and so might have an opinion there.
In general, I think it's fine to implement TAP 15 with a couple of additional restrictions if that leads to simpler code. We can even suggest these adaptions in the TAP. |
Sorry, haven't had time to fully follow everything, but why can't implementations like python-tuf do the following? Inside Am I missing something? |
The problem comes from the fact that we store delegated roles as a dictionary attribute inside the Summarized, the solutions proposed what to do when succinct hash delegation is used are as follows:
I think I am for option |
Let's be clear about the decisions we make: option 2 prevents multiple succinct delegations, a feature the TAP author just confirmed was intentional (even if possibly not important). There are two discussions going on at the same time here, I'll try to separate them: 1. what should the TAP say
2. How we implement the TAP, do we implement it exactly or with modifications?
|
Agree with this and all of the above notes are great thoughts. More and more I agree it's important to try to be fully compliant with the current version of the TAP. We will have more discussions with @jku and hopefully some of the participants in this thread in my pr #1948 and if there are some conclusions from it will write here. |
Add a unique identifier for delegated roles using a succinct hash delegations. This functionality is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Mypy complained that it's possible to have DelegatedRole.name with a value of "None" which is not a string. That's why I had to add special handling for this special case when succinct hash delegations are used and return the name of the first bin as the supposed DelegatedRole.name. Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
Why don't we take a literal step back here? Maybe, and Jussi suggests this in his last comment, the reason why implementing this is tricky is because the metadata format in TAP 15 is tricky. Maybe (putting on my ER-modeler hat) the "succinct hash delegation object" is just too different from "delegation role" objects? What about this alternative format: {
"keys" : {
KEYID : KEY,
...
},
"roles" : [
{
"name": ROLENAME,
"keyids" : [ KEYID, ... ] ,
"threshold" : THRESHOLD,
("path_hash_prefixes" : [ HEX_DIGEST, ... ] |
"paths" : [ PATHPATTERN, ... ]),
"terminating": TERMINATING,
}, ...
],
"succinct_hash_delegations": [ # better name pending
{
"keyids" : [ KEYID, ... ],
"threshold" : THRESHOLD,
"terminating": TERMINATING,
"delegation_hash_prefix_len" : BIT_LENGTH, # better name pending
"bin_name_prefix" : NAME_PREFIX # better name pending
}, ...
]
} I am aware that the objects share |
I like this idea. It maintains backwards compatibility by leaving the existing Does this solve the issue with the way metadata api identifies delegations? I suppose with the new object it makes a clear place for a new codepath to identify hashed bin delegations without a name for each delegation. |
Yes, or maybe even shorter:
IMO it makes it more obvious. We no longer need a dictionary whose keys can be either a role name or something else, identifying either an individual role or a collection of roles. We would just use two different dictionaries/datastructures. |
That is true, but we might want to consider making some backwards incompatible decisions in the {
"keys" : {},
"roles" : []
"hash_bins": [] # name TBD
} The backwards compatible way would be to make |
@awwad just pointed out that the order in At any rate, we need to define if delegations in |
I would think it should be roles first. However, I think mixing them is a
fairly bad idea overall though.
…On Thu, Apr 28, 2022 at 12:02 AM Lukas Pühringer ***@***.***> wrote:
@awwad <https://github.com/awwad> just pointed out that the order in roles
is important when traversing the delegation tree. Now if we have two
fields, we cannot interleave "normal" delegations from the roles list and
succinct hash bin delegation from the hash_bins field, which is something
that was possible in the original TAP 15 proposal. Although, I doubt that
there is actually a use case for it.
At any rate, we need to define if delegations in roles are prioritized
over delegations in hash_bins, or the other way around.
—
Reply to this email directly, view it on GitHub
<#1943 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGRODYAMHGRPSXEN74UXMTVHFQIRANCNFSM5SV6QW7Q>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
I already commented elsewhere but this has some very tricky edge cases: it may look compatible but is actually a potential security hole. If both succinct_hash_delegations and roles are allowed in delegations then old clients that see new metadata would consider succinct_hash_delegations just unidentified extra data, something that the spec explicitly allows. So old clients would happily use new metadata without actually understanding the delegations defined in it. This is likely not what we want. |
This is always already a risk with accepting and ignoring unknown fields (except only to check if any signatures cover them), correct? |
I don't think so. In this case we are changing the way delegations are supposed to be understood, while leaving the format seemingly compatible. The old client will think it has understood the delegation correctly when it has only understood a part of it. It's possible that there are no security issues here but I don't like the ambiguity: I would rather choose a design where old client fails to process the whole delegations object if the delegations object contains a delegation client does not understand. |
A solution to this would be to make this TAP part of a major version change. Clients check the version when downloading, so would know that the metadata shouldn't be parsed by an older client. If we do that, we could then require that metadata includes either, but not both of |
I think here you meant |
This certainly does it but I don't think it's necessary: If succinct delegations are not used, the old clients would still work fine with any of the formats we've discussed. Bumping major version would mean they would be made artificially incompatible which feels quite drastic. I think it would be acceptable if the spec major version stays the same, but we just document that old clients will not work if repository uses succinct delegations (and then we really make sure that the format we design can't accidentally half-work with old clients like I described earlier). |
Add a SuccinctHashDelegations.get_bin_name() API call which returns the bin name of a given sequential bin number. This is useful to easily get the name of the first bin which can be used as a unique identifier for delegated roles using a succinct hash delegations. A unique identifier for such delegated roles with succinct hash is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
Add a SuccinctHashDelegations.get_bin_name() API call which returns the bin name of a given sequential bin number. This is useful to easily get the name of the first bin which can be used as a unique identifier for delegated roles using a succinct hash delegations. A unique identifier for such delegated roles with succinct hash is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
Add a SuccinctHashDelegations.get_bin_name() API call which returns the bin name of a given sequential bin number. This is useful to easily get the name of the first bin which can be used as a unique identifier for delegated roles using a succinct hash delegations. A unique identifier for such delegated roles with succinct hash is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
Change the current pr and experiment with Luka's suggestion outlined here: theupdateframework#1943 (comment) For the ease of implementation, I have additionally decided that: - "roles" and "succinct_hash_delegations" attributes in the Delegations class are mutually exclusive - there could be only one "succinct_hash_delegations" - I didn't create a new common class between "DelegatedRole" and "SuccinctHashDelegation" classes as I didn't notice any meaningful improvements - I have decided to leave Delegations.find_delegation() even though it's not used by the client as that seemed like a logical API call to have Signed-off-by: Martin Vrachev <[email protected]>
Add a SuccinctHashDelegations.get_bin_name() API call which returns the bin name of a given sequential bin number. This is useful to easily get the name of the first bin which can be used as a unique identifier for delegated roles using a succinct hash delegations. A unique identifier for such delegated roles with succinct hash is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
Change the current pr and experiment with Luka's suggestion outlined here: theupdateframework#1943 (comment) For the ease of implementation, I have additionally decided that: - "roles" and "succinct_hash_delegations" attributes in the Delegations class are mutually exclusive - there could be only one "succinct_hash_delegations" - I didn't create a new common class between "DelegatedRole" and "SuccinctHashDelegation" classes as I didn't notice any meaningful improvements - I have decided to leave Delegations.find_delegation() even though it's not used by the client as that seemed like a logical API call to have Signed-off-by: Martin Vrachev <[email protected]>
I have implemented @lukpueh suggestion from the comment here https://github.com/MVrachev/tuf/tree/new-suggestion. In my prototype, I have additionally decided that:
|
Some initial comments:
Any comments on how complex this felt to implement vs the other approach @MVrachev ? Assuming we manage to polish the API, I feel like this looks a little more manageable to me -- the complexity is now contained in places where I expect it (although the key management issues are an unfortunate side effect). |
Some initial comments from me as well on the prototype based on Lukas suggestion:
Agree, I spent a good amount of time optimizing the code and making it smaller.
Agree, I wanted to simplify it, but I wasn't sure how as if I just return succinct hash delegation instead of the name then I will add the first bin role name to be visited instead of the actual bin name reponsible for that target path.
Yep, agree it looks ugly when I am not using a common class between those two. I can't say I just return
Yes, the suddenly added complexity of those two API calls probably shows that those functions tries to cover a more generic case than it should.
It felt that in some places I had to add more code just to make sure I am handling all cases related that only one of
I have a feeling that this is a more logical design to rely on |
There could be some alternative design here... Throwing suggestions on the wall: terminating is only needed once in updater so what if you return a tuple of |
There was a TAP 15 design meeting. What we have decided is summarized here: theupdateframework/taps#154 (review). We have decided to drop the |
Add a SuccinctRoles.get_bin_name() API call which returns the bin name of a given sequential bin number. This is useful to easily get the name of the first bin which can be used as a unique identifier for delegated roles using a succinct_roles. A unique identifier for such delegated roles with succinct_roles is required by our implementation of Delegations.roles where the keys are DelegatedRole.name attributes and values are DelegatedRole objects and the fact that when succinct hash delegations are used DelegatedRole.name should be populated with "None". Solves: theupdateframework#1943 Signed-off-by: Martin Vrachev <[email protected]>
We have decided that |
Description of issue or feature request:
We are working to implement TAP 15 (see #1909).
There it's said that:
meaning that the
DelegatedRole.name
attribute is not required.That seems to be a problem for us as until now we are relying on its existence to uniquely identify roles:
(see
Delegations.from_dict()
implementation)python-tuf/tuf/api/metadata.py
Line 1472 in 10f9fea
One solution to this problem could be providing an additional
ID
number that will serve as a unique identifier for roles.This approach is widely used by databases.
But then we have the next question what to do about
DelegatedRole.to_dict()
where we currently providename
:python-tuf/tuf/api/metadata.py
Line 1359 in 10f9fea
In summary what we should do is:
Delegations
DelegatedRole.to_dict
The text was updated successfully, but these errors were encountered: