Skip to content
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 14: Managing TUF Versions #136

Open
mnm678 opened this issue Apr 29, 2021 · 6 comments
Open

Discussion of TAP 14: Managing TUF Versions #136

mnm678 opened this issue Apr 29, 2021 · 6 comments
Milestone

Comments

@mnm678
Copy link
Contributor

mnm678 commented Apr 29, 2021

This TAP was introduced in #107.

A reference implementation will be needed before this TAP is accepted.

@mnm678 mnm678 added this to the TUF 2.0.0 milestone Apr 29, 2021
@JustinCappos
Copy link
Member

JustinCappos commented Apr 30, 2021 via email

@mnm678
Copy link
Contributor Author

mnm678 commented May 5, 2021

I think the rollback attack would be tricky with the client updating their trusted root metadata, but just to be safe I added a more explicit specification rollback check in #139.

@erickt
Copy link

erickt commented Sep 11, 2021

If I’m reading TAP-14 correctly, it seems that repositories must now support browsing directories. Could we consider alternatives for this? There’s no canonical way for listing directories on a web server, and so most implementations just present a non-portable human readable interface.

Furthermore, even if there was a convention, these directories could be quite large, so it’d add a lot of overhead to the update process.

Instead, I can think of two alternatives. First, we could have a top-level file that lists all the metadata directories. But this has the downside of how do we evolve this file over time.

Second, the root metadata could contain a field for an array of the spec versions in the repo that it knows about that are greater than the current version.

This has a number of advantages. First, the client must know how to read this field, since it needs the ability to read the root metadata. Second, the field is signed, and less subject to attack. Third, we can skip an extra request. Forth, this allows an old client to update, even if we stop updating the old metadata.

To do the last one, presume we have a repo with metadata for versions 1, 2 and 3. We marked the version 1 root as obsolete, and let the metadata expire. Included in the last transaction of version 1 is a new client that can read version 2. The latest version of 2 then can read version 3.

Then, say we have a client that’s been offline for a while, and only knows how to read version 1. When it comes online, it updates to the latest root from spec version 1. Since the metadata is expired, typically the client would just error out at this point, but because the client can see the metadata is obsolete, it knows it’s stuck in this state. It could decide to instead use the latest expired in version 1 to update the client. Then the new client could be used to update to version 2 of the metadata. Which includes a client that can update to version 3.

@mnm678
Copy link
Contributor Author

mnm678 commented Sep 13, 2021

There are a number of TUF implementations that don't have a traditional filesystem, so I agree that we should consider some alternatives.

I see a few downsides to using a field in root. These may or may not be worth the simplicity of removing the file system structure:

  • If the root metadata format changes (for example Update reference POUF to use DSSE #143), a client on an older version may not be able to find the spec versions. It might be alright to limit future changes so that this field must be accessible.
  • Delegated targets would have to change spec versions in sync with the top-level roles. In some implementations, these delegated targets are controlled by different entities, and so this would take some coordination. Major spec version changes should be rare, so this would only be an occasional annoyance.
  • Metadata from different spec versions would need to be discoverable on the repository. If there is a snapshot metadata for both version 3 and version 4, how are these named?

@erickt
Copy link

erickt commented Sep 13, 2021

If the root metadata format changes (for example Update reference POUF to use DSSE #143), a client on an older version may not be able to find the spec versions. It might be alright to limit future changes so that this field must be accessible.

Yeah, there's a bit of a bootstrapping issue that we need to work around to support this. For Fuchsia, I think I mentioned in a separate ticket we distribute our OS updates with Fuchsia, so a user could put a device running our initial version in a closet, and it still should be able to take an update when plugged in before the device has been End-of-Life-d. So we need them to be able to update to a client version gate, which can then be used to update to the next version gate, and etc until they're fully up to date. So whatever mechanism we chose it needs to support a gradual migration.

Delegated targets would have to change spec versions in sync with the top-level roles. In some implementations, these delegated targets are controlled by different entities, and so this would take some coordination. Major spec version changes should be rare, so this would only be an occasional annoyance.

I haven't actually worked with delegated targets yet, so I don't have much intuition with them yet. Maybe we could have an analogous spec version field in the targets metadata for them? This could allow the core metadata to migrate first, but allow delegated targets to take more time to migrate.

Metadata from different spec versions would need to be discoverable on the repository. If there is a snapshot metadata for both version 3 and version 4, how are these named?

By "version 3 and version 4", do you mean the spec versions for these files, or the metadata versions? Maybe we need another name for this. What if we used the terminology "epoch" or "tuf spec epoch" to avoid this ambiguity? I've seen this used elsewhere.

Anyway, presuming you are referring to tuf spec version / tuf spec epoch, I see this as something that always goes forward in time. We always want to use the latest supported tuf spec version / epoch version that's available. So I'd assume these paths would be 3.0.0/5.snapshot.json and 4.0.0/5.snapshot.json.


Also, coming over from #138, a repository migrating from one POUF to another can break clients, even if the semantics of the TUF spec stay the same. For example, switching from json to DSSE, and maybe down the road to the binary COSE format. Would it make sense to consider a repository version / epoch as well, or in replacement for supporting TUF spec version changes? Having this under repo control could allow for more radical changes like this.

One other small thing. If these subdirectories are only ever the major version, could we name them after the major version as "3/" rather than "3.0.0/"? That'd avoid the risk of a library using the full tuf spec version.

@mnm678
Copy link
Contributor Author

mnm678 commented Sep 14, 2021

I haven't actually worked with delegated targets yet, so I don't have much intuition with them yet. Maybe we could have an analogous spec version field in the targets metadata for them? This could allow the core metadata to migrate first, but allow delegated targets to take more time to migrate.

That could work. And it could be an optional field that's only used if the delegated targets are or could be out of sync with the top-level metadata.

By "version 3 and version 4", do you mean the spec versions for these files, or the metadata versions? Maybe we need another name for this. What if we used the terminology "epoch" or "tuf spec epoch" to avoid this ambiguity? I've seen this used elsewhere.

I agree. I'll update this in my next pass on the TAP. I try to be careful about saying "tuf spec version", but clearly I sometimes forget to type the whole thing :).

Anyway, presuming you are referring to tuf spec version / tuf spec epoch, I see this as something that always goes forward in time. We always want to use the latest supported tuf spec version / epoch version that's available. So I'd assume these paths would be 3.0.0/5.snapshot.json and 4.0.0/5.snapshot.json.

Ok, so you can still use the directory structure, just not browse all of them. That makes sense.

Also, coming over from #138, a repository migrating from one POUF to another can break clients, even if the semantics of the TUF spec stay the same. For example, switching from json to DSSE, and maybe down the road to the binary COSE format. Would it make sense to consider a repository version / epoch as well, or in replacement for supporting TUF spec version changes? Having this under repo control could allow for more radical changes like this.

With the name change to "epoch", I think it makes sense to tie this to either a POUF or tuf spec version change. That way we won't need another mechanism for when the POUF is updated. It also makes philosophical sense, in that the interoperability is tied to the POUF rather than the spec version. I don't think this requires any technical changes to the TAP, but maybe some new framing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants