-
Notifications
You must be signed in to change notification settings - Fork 20
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
Discussion of TAP 8: Key rotation and explicit self-revocation #37
Comments
Hi, @hannesm. I came across an old comment of yours on the issue discussion for TAP 3 (multi-role delegations). (I'm just checking in on the status of TAP 8) |
It looks like GitHub ate my email; yes, I'm working on a revision of TAP8 - unfortunately not yet done, but hopefully by the end of this week. I'll open a PR then and let's discuss in that how to move forward. Sorry for the delay. |
No problem! Thanks, and we're looking forward to TAP 8 revision. |
@JustinCappos asked about TAP 8 during a recent meeting. He was wondering if you've come across any potential issues with TAP 8 while implementing it. |
@vladimir-v-diaz due to other projects, my implementation of tuf + tap8 is only progressing slowly (only doing this in my spare time, working on other projects for funding). so far I have basic tuf nearly finished (in OCaml), and will work over the summer on finalising tuf+tap8. I'll get back to tap8 once implemented, sorry for the delay. |
I think this is a good and wise feature add. I was reviewing @mnm678's TUF PR draft implementing TAP 8 and combed through TAP 8 and chatted with Marina a bit. I think that there are some conceptual issues and a few clarifications that should be made. I'm going to stick to only the two bigger conceptual points for this post: Root Key Rotation Efficiency ImprovementIn the course of the client's traversing the path from the currently trusted root file to the most recent root file, I'm not yet convinced that it's okay to only fetch root files that include key/threshold changes for the root keys: TAP 3 InteroperabilityI think that the particular (additional) TAP 3 interoperability advertised is a little too ambitious -- too complex in code and in concept -- and so probably inadvisable. Imagine that role X delegates to two roles A and B (with two thresholds and two key sets). Which of the following behaviors make sense?
Related to the conceptual complexity, it's worth noting that the code to do the second bullet point would mangle the natural structure that exists currently, I think (process a role, move to its delegations). Just knowing what rotate filename to look for in the multi-role case is complicated here, because the keyids in a multi-role delegation to roles B+C may be changed by changes to the keyids for B. (That said, abstractly: this extra type of multi-role rotation is a feature that hints at the possible value of further reducing the significance of roles in favor of key sets. It's possible that that feature (and possibly TAP 3 and other properties of TUF) would make more sense with a further diminishment of the role of "roles" vs delegations. If there's room to consider something like that, maybe the proposed TAP 3 multi-role rotation would make more sense. Food for thought for someday.) |
After talking with @JustinCappos and @awwad , we found that there are two categories of use cases that TAP 8 is trying to address. The first (role rotation) involves a threshold of keys from a role rotating the set of keys for that role. This includes the role adding new keys (think adding a new developer to the team) as well as removing a key, changing a key, or changing the threshold. The second (individual key rotation) involves rotating an individual key (as for key revocation) everywhere that that key is used. Unfortunately, due to issues with ordering and naming, I do not think it is possible to include both of these features without some major spec changes. Because rotate files are named using keyids, changing keyids with either of the above methods would make it impossible to determine if the other type of rotation is happening elsewhere. Either of these options would provide some useful features, but I think that the first covers more of the use cases discussed in the TAP. The second case could be achieved using role rotation if the key owner coordinated with all of their associated roles (or could be done individually for any roles with a threshold of 1). However, a case could be made for expediting individual key rotation in the case of a compromised key. This process would be faster with the second option. @hannesm Any thoughts about which option we should implement? |
@mnm678, Can you describe in a bit more detail here? Perhaps an example
would help...
…On Wed, Sep 12, 2018 at 12:10 PM mnm678 ***@***.***> wrote:
After talking with @JustinCappos <https://github.com/JustinCappos> and
@awwad <https://github.com/awwad> , we found that there are two
categories of use cases that TAP 8 is trying to address.
The first (role rotation) involves a threshold of keys from a role
rotating the set of keys for that role. This includes the role adding new
keys (think adding a new developer to the team) as well as removing a key,
changing a key, or changing the threshold.
The second (individual key rotation) involves rotating an individual key
(as for key revocation) everywhere that that key is used.
Unfortunately, due to issues with ordering and naming, I do not think it
is possible to include both of these features without some major spec
changes. Because rotate files are named using keyids, changing keyids with
either of the above methods would make it impossible to determine if the
other type of rotation is happening elsewhere.
Either of these options would provide some useful features, but I think
that the first covers more of the use cases discussed in the TAP. The
second case could be achieved using role rotation if the key owner
coordinated with all of their associated roles (or could be done
individually for any roles with a threshold of 1).
However, a case could be made for expediting individual key rotation in
the case of a compromised key. This process would be faster with the second
option.
@hannesm <https://github.com/hannesm> Any thoughts about which option we
should implement?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XD3nXfZ2X0VuX3iNY_MTf_m0CirGsks5uaTH7gaJpZM4NsGtG>
.
|
Sure, here are some example scenarios for role vs key rotation. For role rotation, say there's a developer role that has 3 developers who each have a key (A, B, and C) associated with the role with a threshold of 2 keys. A and B would be able to sign a rotate file that adds D to the role, leaving the threshold at 2. The role would then have 4 keys (A, B, C, D) and a threshold of 2. Using this method, a threshold of keys in the role can make any changes to the key/threshold makeup of the role without the delegator needing to sign a new file. This method could also be used for key rotation/revocation. If B wanted to change their key to B2, they could get together with A to sign a rotate file that includes keys A, B2, C, and D. However, if B's key was also used as part of the testing role, B would remain a valid key in that role unless an additional rotate file was created for the testing role. For key rotation, if C wanted to change their key (possible compromise, etc) they would sign a rotate file with the new key C2. This would then have any role that formerly trusted C trust C2 instead. In this method, a key can make changes to itself (or self revoke by creating a cycle) but any changes to roles would have to come from the delegator. These are both useful features, but a problem arises when trying to implement both. If C rotated its key to C2 using key rotation, a file specifying that A, B, C should be changed to A, B, C, D using role rotation would no longer be found as the system would look for a file changing A, B, C2 (rotate filename are role.rotate.ID where ID=sha256(keys.threshold)). Removing the keys from the filename would create some confusion as to when various rotate files are valid and make cycle detection more challenging. So as far as I can tell this leaves us with picking either role rotation or key rotation. |
As a further note: the TAP 3 Interoperability comment I made above pertains to the role/keyset-rotation feature, which is implicit in the TAP as it exists currently, and the current "Interoperability with TAP 3" section. |
thanks for your comments.
|
A couple more thoughts: root file rotation - An option would be to include the TAP 3 - I think the tricky part would be how to find the rotate file. If there’s a delegation to roles [A, B, C] which have keys [A1, A2], [B1, B2], [C1, C2]. Using a combination of keyids to find the rotate file wouldn’t work if A, B, or C did an individual rotation, so we would need to define a different naming scheme for the rotate file for the multi-role delegation (it would need to include at least the role threshold and role names). This would rely on role names being used as identifiers for the rotate file which brings up some issues with overlapping role names. Additionally, I made a couple of changes to TAP8 (here) that clarify roles and keys as well as making a slight change to the timing of a rotate file check to ensure the file is always found. |
@hannesm @JustinCappos Any thoughts about the role vs key rotation mentioned above? I was planning to go ahead with role rotation unless there's a reason to do the key rotation instead. |
I see a lot of potential complications with having the root role use the
same mechanism. When you sign metadata is absolutely key in this case and
the consistency and timeliness of the data is really a major question for
rotate files. The user is somewhat reliant on the repository not
withholding rotate files in all cases (in some sort of fork attack). The
root file is the most likely to be out of date for clients that were
pre-loaded with a file from a long while past. So I'd favor the root
mechanism staying as is.
As for where to find the rotate files, I would think they can live in a
single directory in the repo. I don't think there is a problem with this
being the same as the targets directory. I also don't think there would be
a problem with it being its own directory. I would lean slightly toward
the latter because it seems clients should download all rotate files. Is
this your view too?
Also, what about rotate files from different repos? Should they be
pooled? Should revocation apply independent of source?
…On Tue, Oct 2, 2018 at 4:55 PM mnm678 ***@***.***> wrote:
@hannesm <https://github.com/hannesm> @JustinCappos
<https://github.com/JustinCappos> Any thoughts about the role vs key
rotation mentioned above
<#37 (comment)>?
I was planning to go ahead with role rotation unless there's a reason to do
the key rotation instead.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XD7WzoD2Vepukx0utnsOgMT4_e3hdks5ug9LGgaJpZM4NsGtG>
.
|
Root rotation I agree that we should leave the root rotation as is. There doesn’t seem to be a good way to ensure rotate files are found for root, and additionally the spec-version, etc in root should be read for each version of the root file, which makes more sense with the current mechanism. Location of rotate files I think putting them in their own directory makes sense. The main issue here is making sure that the client sees any available rotate files. Spec-version update While looking at root key rotation, it seems like what to do on a spec-version update is not made clear. I’ve come up with a couple of ideas here, and I think the second makes more sense for most uses. 1: Require all changes to be backwards compatible. This allows clients and servers to update independently, but I think it creates more problems than it solves because it limits the potential of TUF going forward. TAP 8, along with other proposed changes would break on older versions. 2: Require clients to update. Specify that as soon as they see an increase in the spec-version, they must update their client to finish the update process. This might cause problems if the client for some reason can’t/doesn’t want to update, but it allows for more flexibility and potential security fixes in TUF. Pooling Rotate Files I think that they should be dependent on the role. The use case of a person entering/leaving a role makes the most sense if the rotate file only applies to that role in that repository. That way if person A left a role, they would still have access to their other roles. However, it might be nice if the self-revocation worked across repos. |
I think there is another option for spec file changes --- require a version
of the file with the old spec number (and of course in the old format) that
tells clients where to get a version of the client so they can update.
I don't think this is a TAP 8 problem though. This feels like something
that should be pulled out into another TAP.
I don't really understand what you mean in the pooling rotate files part.
Perhaps this is because I think you're imagining cases where there are
multiple keys per role. Can we start from the single key per role case and
build up from there?
…On Thu, Oct 4, 2018 at 2:30 PM mnm678 ***@***.***> wrote:
Root rotation
I agree that we should leave the root rotation as is. There doesn’t seem
to be a good way to ensure rotate files are found for root, and
additionally the spec-version, etc in root should be read for each version
of the root file, which makes more sense with the current mechanism.
Location of rotate files
I think putting them in their own directory makes sense. The main issue
here is making sure that the client sees any available rotate files.
Spec-version update
While looking at root key rotation, it seems like what to do on a
spec-version update is not made clear. I’ve come up with a couple of ideas
here, and I think the second makes more sense for most uses.
1: Require all changes to be backwards compatible. This allows clients and
servers to update independently, but I think it creates more problems than
it solves because it limits the potential of TUF going forward. TAP 8,
along with other proposed changes would break on older versions.
2: Require clients to update. Specify that as soon as they see an increase
in the spec-version, they must update their client to finish the update
process. This might cause problems if the client for some reason
can’t/doesn’t want to update, but it allows for more flexibility and
potential security fixes in TUF.
Pooling Rotate Files
I think that they should be dependent on the role. The use case of a
person entering/leaving a role makes the most sense if the rotate file only
applies to that role in that repository. That way if person A left a role,
they would still have access to their other roles. However, it might be
nice if the self-revocation worked across repos.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XDytwWIQW-9ykutvNZPdinZaX9Slfks5uhlO0gaJpZM4NsGtG>
.
|
@JustinCappos Here’s some additional explanation of the pros and cons of pooling rotate files across repositories: A rotate file is named using the role name, keys, and threshold. In a situation with pooled rotate files, any roles that share a name, keys, and threshold would be rotated together. In the case of a self-revocation, this is probably the best behavior. If a key was compromised, that same key will be compromised elsewhere. However, if there were two roles in separate repos with the same name (for example a developer role) this could cause an unwanted rotation. For example: people A, B, and C are all developers on projects foo and bar. Person C decides to leave foo to focus on bar. A and B sign a rotate files that takes C off of the project foo. This rotate file will be seen by anyone using bar as well and C will effectively be removed from both projects instead of just foo. Essentially, this is a tradeoff between allowing a revocation to be seen by more people at once and allowing the rotate mechanism to be independent. However, I think it is unlikely that all uses of a key would fit under the same rotate file (it might be used for different role names, with different other keys, etc), so I feel it makes more sense to have the rotate files only work within the same repository to prevent unwanted rotations. |
Why wouldn't the project name be part of the signed rotate file? If so,
then this avoids the specific case you mention. It should only be a
problem then if there are multiple repositories that have the same role
name with the same developers that want to do distinct rotations...
…On Fri, Oct 5, 2018 at 11:27 AM mnm678 ***@***.***> wrote:
@JustinCappos <https://github.com/JustinCappos> Here’s some additional
explanation of the pros and cons of pooling rotate files across
repositories:
A rotate file is named using the role name, keys, and threshold. In a
situation with pooled rotate files, any roles that share a name, keys, and
threshold would be rotated together. In the case of a self-revocation, this
is probably the best behavior. If a key was compromised, that same key will
be compromised elsewhere. However, if there were two roles in separate
repos with the same name (for example a developer role) this could cause an
unwanted rotation. For example: people A, B, and C are all developers on
projects foo and bar. Person C decides to leave foo to focus on bar. A and
B sign a rotate files that takes C off of the project foo. This rotate file
will be seen by anyone using bar as well and C will effectively be removed
from both projects instead of just foo.
Essentially, this is a tradeoff between allowing a revocation to be seen
by more people at once and allowing the rotate mechanism to be independent.
However, I think it is unlikely that all uses of a key would fit under the
same rotate file (it might be used for different role names, with different
other keys, etc), so I feel it makes more sense to have the rotate files
only work within the same repository to prevent unwanted rotations.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XDyeoQ8zJ3DCdJ2vA_vYcycj35HDBks5uh3pqgaJpZM4NsGtG>
.
|
@JustinCappos I think it would be possible to prevent all collisions by adding fields to the filename, but I'm not sure how many use cases there would be for the pooled rotate files considering how much is specified in the rotate filename. It would only be useful if repositories shared role names, keys, and thresholds as well as project name if that was added to the filename. In most cases, revoking a key would still require a rotate file for each use of the key. |
You could just put the repo URL, etc. in the file name too, but I feel this
is overkill.
My intuition is that requiring role names to be unique to the set of
signing keys is adequate. Tying rotations to repos feels like overkill at
this point and may make it harder for users to reliably rotate keys. I
could imagine several groups running separate rotate file servers that
users pull from to get the latest copies of rotated keys...
…On Thu, Oct 11, 2018 at 1:04 PM mnm678 ***@***.***> wrote:
@JustinCappos <https://github.com/JustinCappos> I think it would be
possible to prevent all collisions by adding fields to the filename, but
I'm not sure how many use cases there would be for the pooled rotate files
considering how much is specified in the rotate filename. It would only be
useful if repositories shared role names, keys, and thresholds as well as
project name if that was added to the filename. In most cases, revoking a
key would still require a rotate file for each use of the key.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XD3PKO4PSYjQPloyIkoiDBJ0Nhy2Pks5uj3opgaJpZM4NsGtG>
.
|
I made some proposed changes to the spec based on this discussion. Specifically, I made changes to root rotation, location of rotate files, getting rid of unintended cycles, and what to do with conflicting rotate files. More details are in the PR. |
While writing a revision to the tap, I found a couple of additional interesting points. First: What should the rotate file be named? The filename was previously defined as role.rotate.ID, with ID as the sha256 hash of the keys (in lexicographical order) and the threshold (in ascii). Now that rotation cycles are allowed (through adding the hash of the previous rotate file), these filenames could collide. I propose adding the hash of the previous file to the filename to prevent this ambiguity. The ID would still have to be in the filename as the first rotate file would always have a previous file of null, so a collision could occur in the first rotate file after a re-delegation (ex: role A is delegated to, creates a rotate file, is delegated to with a new key, creates another rotate file that will have the same previous hash as the first). One potential downside of including both the ID and previous file hash is a much longer filename. Second: Does the rotate file need to contain both the new keys and a list of new keyids? From my understanding the key structure contains the keyids, so this seems like redundant information to include in the rotate file. Third: Should clients work backward from the most recent rotate file, or forward from the delegation? Now that rotate files point backward, would it make sense to look for the most recent rotate file? I think that it would be better to still start from the delegation to ensure that the chain of trust is maintained (so stay with the current mechanism of getting the delegation, then repeatedly looking for rotate files with the current keys). @JustinCappos @hannesm I’d appreciate any input/insight into any of these issues, or any other comments on the changes to the TAP8 spec (found here). |
The ID would still have to be in the filename as the first rotate file
would always have a previous file of null, so a collision could occur in
the first rotate file after a re-delegation (ex: role A is delegated to,
creates a rotate file, is delegated to with a new key, creates another
rotate file that will have the same previous hash as the first).
I think this raises a bigger point. Should one be able to reuse a role
name after revocation? If this is prevented, then there is no issue here.
Right now, does the TUF spec specifically forbid a server from having two
different roles (with different sets of keys) use the same role name? This
may also factor in...
Second: Does the rotate file need to contain both the new keys and a list
of new keyids? From my understanding the key structure contains the keyids,
so this seems like redundant information to include in the rotate file.
I do not see why both would be needed, but I may be missing something.
Third: Should clients work backward from the most recent rotate file, or
forward from the delegation? Now that rotate files point backward, would it
make sense to look for the most recent rotate file? I think that it would
be better to still start from the delegation to ensure that the chain of
trust is maintained (so stay with the current mechanism of getting the
delegation, then repeatedly looking for rotate files with the current keys).
I'm not sure how you can work backwards efficiently. Do you have to hash
all files with the same keyID to figure out what previous file has the
correct hash? Is the backpointer more explicit (such as a file name)?
|
Role names: I think another question is whether we want the rotate mechanism to replace delegation here. If the delegator is allowed to continue handling key rotation, they have to be allowed to re-delegate to the same rolename (they delegate to role A with key a, then later change this to role A with key b). If we want to eliminate this re-delegation use case, we could prevent role name reuse by delegators. I think taking this power away from delegators will lead to a lot of confusion (for example, they delegate to a developer role, then to developer_1 role, etc until they are delegating to developer_42 which I think makes the role's purpose less clear). Working Backwards: |
Role names:
The TUF spec does not specifically forbid roles with the same role name,
but in practice it would not work as the role's metadata file is named
rolename.json.
Okay, thanks! This makes sense.
I think another question is whether we want the rotate mechanism to
replace delegation here. If the delegator is allowed to continue handling
key rotation, they have to be allowed to re-delegate to the same rolename
(they delegate to role A with key a, then later change this to role A with
key b). If we want to eliminate this re-delegation use case, we could
prevent role name reuse by delegators. I think taking this power away from
delegators will lead to a lot of confusion (for example, they delegate to a
developer role, then to developer_1 role, etc until they are delegating to
developer_42 which I think makes the role's purpose less clear).
Right, but it also seems easier to make a mistake when delegating if you
have the same name w/ multiple keys (some revoked).
I'm not sure what is better here. @hannes Mehnert <[email protected]>,
can you chime in?
… |
@mnm678 thanks for your work:
not sure I can follow here, since a rotate file contains the old keys, and also the previous hash, and its filename is constructed by a hash over the content. I may need a more complete example.
my intuition is that you can always delegate to the rotated key, and as outlined below the client workflow handles this well.
|
@hannesm @JustinCappos First, the hash of the previous filename is included in the next filename to allow for cycles in rotation, to be used if a person/key leaves a team and then later rejoins the team. In this case a role foo with initial key A could create foo.rotate.A.null to rotate to key B, then foo.rotate.B.prev to rotate back to A, then foo.rotate.A.prev to rotate to key C. This ensures that foo.rotate.A.null and foo.rotate.A.prev have different names no matter when this cycle occurs. Currently, a new delegation breaks any existing rotate chain for a role and can lead to confusion about which keys to trust, especially if a previously revoked key is later delegated to. For example, if key A is delegated to for role foo, then A rotates to key B (creating foo.rotate.B.null), then B to key C (creating B.rotate.C.prev), then the delegator changes the delegation to key B, should the client use key B or key C? I think that it makes sense for the client to use key C, but to do so it would need to find B.rotate.C.prev instead of B.rotate.C.null. This especially applies if key C was a null key (creating a revocation). The following is a system to make that happen. I propose treating all rotate files as a chain of trust associated with a role name. The chain of trust starts with the initial delegated key, and goes through any rotate files to the current trusted key. The delegator can point to any key in this chain, and the client can check if this is consistent by using the filenames and previous fields to treat rotate files as a doubly linked list. If this chain is broken for any reason (a rotate to null of any key in the chain, or a delegation to a key not in the chain), then the role name is no longer valid, and trust must be delegated to a new role name to continue. The chain of trust ensures that it is clear to both the client and delegator which key is trusted at any given time. All rotate files associated with a role name will be a part of the same chain, and once this chain is no longer valid a new chain with a new name is delegated to. This has the added benefit of allowing the server to delete unused rotate files after trust has been delegated away from that chain. One downside of this proposed method is that existing delegators might have to change their delegation process to comply with the new spec. To change keys without the use of rotate files, the delegator would have to delegate to a new role name with the new key. TAP 8 is already a non-backwards compatible change, so I think that this is not a major concern. Client workflow: 1 look for rotate files and find foo.rotate.A.null This ensures that if foo.rotate.A.null contained a revocation, the client would see this before verifying foo. |
I agree and like this with the proviso that there also not be any
additional rotate files that are not in the chain. A well behaving repo
should cull these.
Justin
…On Thu, Nov 1, 2018 at 12:42 PM mnm678 ***@***.***> wrote:
@hannesm <https://github.com/hannesm> @JustinCappos
<https://github.com/JustinCappos>
Clarifying key revocation:
I have a few thoughts about the role name discussion. Specifically how to
ensure a key revocation is always seen by the client, and how to use
delegations to ensure they don’t contradict rotate files.
First, the hash of the previous filename is included in the next filename
to allow for cycles in rotation, to be used if a person/key leaves a team
and then later rejoins the team. In this case a role foo with initial key A
could create foo.rotate.A.null to rotate to key B, then foo.rotate.B.prev
to rotate back to A, then foo.rotate.A.prev to rotate to key C. This
ensures that foo.rotate.A.null and foo.rotate.A.prev have different names
no matter when this cycle occurs.
Currently, a new delegation breaks any existing rotate chain for a role
and can lead to confusion about which keys to trust, especially if a
previously revoked key is later delegated to. For example, if key A is
delegated to for role foo, then A rotates to key B (creating
foo.rotate.B.null), then B to key C (creating B.rotate.C.prev), then the
delegator changes the delegation to key B, should the client use key B or
key C? I think that it makes sense for the client to use key C, but to do
so it would need to find B.rotate.C.prev instead of B.rotate.C.null. This
especially applies if key C was a null key (creating a revocation). The
following is a system to make that happen.
I propose treating all rotate files as a chain of trust associated with a
role name. The chain of trust starts with the initial delegated key, and
goes through any rotate files to the current trusted key. The delegator can
point to any key in this chain, and the client can check if this is
consistent by using the filenames and previous fields to treat rotate files
as a doubly linked list. If this chain is broken for any reason (a rotate
to null of any key in the chain, or a delegation to a key not in the
chain), then the role name is no longer valid, and trust must be delegated
to a new role name to continue.
The chain of trust ensures that it is clear to both the client and
delegator which key is trusted at any given time. All rotate files
associated with a role name will be a part of the same chain, and once this
chain is no longer valid a new chain with a new name is delegated to. This
has the added benefit of allowing the server to delete unused rotate files
after trust has been delegated away from that chain.
One downside of this proposed method is that existing delegators might
have to change their delegation process to comply with the new spec. To
change keys without the use of rotate files, the delegator would have to
delegate to a new role name with the new key. TAP 8 is already a
non-backwards compatible change, so I think that this is not a major
concern.
Client workflow:
If the client only checks rotate files after signature verification fails,
they might miss a revocation. I propose the following workflow:
1 look for rotate files and find foo.rotate.A.null
2 verify that foo.rotate.A.null verifies and establishes key B
3 read the file foo
4 file foo successfully verifies with key B
This ensures that if foo.rotate.A.null contained a revocation, the client
would see this before verifying foo.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XD47CLH5H6P1TLSasNCdFaQHhRd5xks5uqyRtgaJpZM4NsGtG>
.
|
@JustinCappos One option would be to require delegation to a new key after a revocation. This requirement would allow the chain of rotate files to start again from that new key. The old rotate files would still be around, but the new chain would not see them as long as the new key and any future keys are not part of the old chain. For example, if the timestamp role has an initial key of A, which is rotated to B, then self-revoked, the root can then delegate to a key C (but not to A or B) to start a new chain of trust. A and B would not be allowed in the new chain of trust. This change could apply to all roles or be different for the TUF-defined roles (with other roles following the original proposal). Any other ideas about how to handle this? |
I don't know whether this makes it easier or harder, but I'm also curious
how TAP 5 interacts with this...
My thinking is that the root role's metadata must point to a valid chain
for the stored snapshot, etc. files. Hence they can have a single
canonical name. (Note, that I'm ignoring the 'consistency' problem that
will occur if you read files during an update, because we have this issue
many places.)
…On Mon, Nov 5, 2018 at 1:37 PM mnm678 ***@***.***> wrote:
@JustinCappos <https://github.com/JustinCappos>
One potential problem with this proposal is the roles defined in the TUF
spec (timestamp, snapshot, etc). These roles can't be delegated to new
rolenames in the case of a revocation as they are hardcoded in the spec
(the client will always look for timestamp.json for example).
One option would be to require delegation to a new key after a revocation.
This requirement would allow the chain of rotate files to start again from
that new key. The old rotate files would still be around, but the new chain
would not see them as long as the new key and any future keys are not part
of the old chain. For example, if the timestamp role has an initial key of
A, which is rotated to B, then self-revoked, the root can then delegate to
a key C (but not to A or B) to start a new chain of trust. A and B would
not be allowed in the new chain of trust.
This change could apply to all roles or be different for the TUF-defined
roles (with other roles following the original proposal).
Any other ideas about how to handle this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA0XD2Y1S1K504Y0M-JxFfqrXYs3E_7yks5usIVPgaJpZM4NsGtG>
.
|
@JustinCappos @hannesm For TAP 5 I think it makes sense to keep the rotate files on the repository. The client would determine the current valid key using the rotate mechanism, then download the file from the provided url and check against the key. Is there any reason the rotate files should go on the mirror instead? |
I've been working on a POC for this TAP, and have a couple of simplifications that I'd like to make, but want to get some feedback first.
|
I'm assuming that you also list the counter in the file so that the repo, etc. cannot change it. Perhaps expressly listing the filename in the file is the easiest way to do this. If so, I don't spot a flaw with moving to the model you describe. Are these counter numbers required to be sequential? What about a client that wishes to rotate their key on different systems? Suppose Alice rotated to Alice_key2 on repo 1. On repo 2 Alice only uses Alice_key2. Alice now wants to rotate to Alice_key3. What does the counter look like for this file? Can it be uploaded to both repositories? I'm not sure this is changed by what you propose, but can you refresh my memory about whether all clients retrieve / analyze all rotate files? |
If the same set of rotations are done on both repositories, the same rotate files can be used. If one of the rotate files in the sequence was not included on one repository (as in your example), then the counter would be out of sync and Alice would need to generate two rotate files (alice.rotate.0 and alice.rotate.1). With proper tooling this should not be a big issue.
Yes, they download the entire rotate chain. This ensures that any rotates to null are detected. This is the same in my proposal, except that the counter makes the chain more human-readable. |
Why is having the version numbers be sequential important?
…On Thu, Jan 26, 2023 at 11:10 AM Marina Moore ***@***.***> wrote:
Are these counter numbers required to be sequential? What about a client
that wishes to rotate their key on different systems? Suppose Alice rotated
to Alice_key2 on repo 1. On repo 2 Alice only uses Alice_key2. Alice now
wants to rotate to Alice_key3. What does the counter look like for this
file? Can it be uploaded to both repositories?
If the same set of rotations are done on both repositories, the same
rotate files can be used. If one of the rotate files in the sequence was
not included on one repository (as in your example), then the counter would
be out of sync and Alice would need to generate two rotate files
(alice.rotate.0 and alice.rotate.1). With proper tooling this should not be
a big issue.
I'm not sure this is changed by what you propose, but can you refresh my
memory about whether all clients retrieve / analyze all rotate files?
Yes, they download the entire rotate chain. This ensures that any rotates
to null are detected. This is the same in my proposal, except that the
counter makes the chain more human-readable.
—
Reply to this email directly, view it on GitHub
<#37 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGRODYWFQXI3ISIYYGTAB3WUKOXVANCNFSM4DNQNNDA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
This ensures that the rotate files are processed in the correct order. Each file will be signed by a threshold of previous keys, and so the client needs to get them in order to ensure they end up with the correct key. |
I'm still worried about the complexity of this feature (while a nice one for decentralised control) vs the benefits. I haven't heard of a use case for this beyond Haskell and Fulcio(?). It will make at least the TUF client that much more complicated to implement and test for correctness. |
In the case of large TUF deployments (PyPI, etc), having the top-level targets responsible for all key changes is not sustainable. Every time a maintainer is added to a project a repository admin has to be notified, find the offline targets key, and use this to sign a new delegation for the project. In many cases these are volunteer administrators, and this is a lot of work to put on them. TAP 8 solves this problem. I have a WIP implementation that only adds or changes about 200 lines of code. This can likely be further simplified. Every feature adds some complexity, but I argue that we have worked to make this particular feature as simple as possible (with changes like #167), and it provides a much-needed improvement to TUF's ease-of-use. |
I see, thanks for the explanation! I wasn't aware that community software repos were a major use case. I also glanced at your WIP implementation, and the changes to the client do look fairly small. I strongly recommend adding these use cases (e.g., community repos, and Fulcio) to the TAP in order to more clearly motivate the TAP. I also think a small benefits vs drawbacks analysis might be helpful. |
Thanks for the feedback! I'll update the TAP. |
+1 to trishanks concerns: the implementation is not simple and it's also not complete (no client caching for example). I don't want to derail reviewing the implementation but I'll leave these comments on the core idea:
The above suggestion is not 100% equivalent to the TAP (as it temporarily creates a situation where there are two levels of foo maintainers) but I would like this TAP to describe why the complexity is warranted over the above solution that seems to require no spec changes. |
Wanted to note @dstufft observation that perhaps a rotate file should also be signed by the new threshold T_2 of signers S_2. Otherwise, you could run into potential cases of abuse where an old threshold of T_1 of signers S_1 could make T_2 of S_2 responsible whether they like it or not. |
For PyPI explicitly we will likely want every new key to have to sign the rotation file, not just a threshold, because the goal for us would be to disallow someone to "force" another person to be associated with their project, without that person's consent. We had this happen in the past when PyPI would allow you to add another person to a project (without invitation or confirmation, just blindly add people), to "steal" their reputation. Sometimes they would also leave the project themselves to make it appear like it came wholly from that person. We've prevented this at the PyPI level, but implementing this TAP for PyPI would mean reintroducing a form of that currently, through the key identities. Of course PyPI could apply it's own logic upon receiving a rotate file, and independently confirm that the key holders are OK with it, but that has to be done entirely out of band and we would have to delay using the rotation file until that happens (which has consequences for what keys the project should be signing with in the future). So it's convenient to implement it by having the new keys sign the rotation file which proves that the key owners agree with the rotation. One other note about having all of the keys sign the rotation file is it makes accidental key inclusions harder, since if you typo the name or something you won't be able to get a signature from that key unless you happen to own that key too. This could possibly cause people to be unable to reach their threshold or to have less of a margin for key compromise than expected. This makes a TUF repository more resilient to misuse. |
Just wanted to note that one way to make this happen is to: (1) specify the threshold such that all signers must sign, and (2) enforcing this check in the package manager that integrates with TUF. |
I should also add that I'm not a fan of fixing things like key IDs are assumed to be SHA2-256 hashes. Not only does it violate the principle of crypto agility in TUF (hence making it difficult to update metadata w/o breaking), but it also violates TAP 12. |
This assumption is removed in this pr: #167 that simplifies the naming of rotate files. |
I did some clean-up on the existing TAP 8 prs (#165, #167, and #172), and added some minor clarifications in #181. Once this is cleaned up, I plan to separate the self-revocation from the self-rotation into separate TAPs (with a new TAP for revocation. This new TAP should be much simpler, and will allow us to include these changes incrementally. |
I probably missed something, but wouldn't it be possible for the owner of a key (or an attacker) to self-rotate an arbitrarily large number of times and effectively DoS the |
This would be a good one to discuss in the TAP. I think this is similar to an existing attack any key holder can do where they upload several different versions of the same metadata file. The mitigation would be for the repository to set rate limits after 1-2 of these have been uploaded (similar to endless data attack, etc). |
I wonder if the delegator could set a maximum number of rotate files before "compaction" is required
|
I added a brief discussion of this in #183 |
TAP 8 proposal is available at https://github.com/theupdateframework/taps/blob/master/tap8.md
Pull requests related to TAP 8:
#20
Discussion of TAP 8 on the TUF mailing list:
https://groups.google.com/d/msg/theupdateframework/Yj1z3PkMRZc/n8wXM4VZBgAJ
The text was updated successfully, but these errors were encountered: