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

TAP13 draft #118

Merged
merged 15 commits into from
Nov 3, 2021
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [TAP 8: Key rotation and explicit self-revocation](tap8.md)
* [TAP 11: Using POUFs for Interoperability](tap11.md)
* [TAP 12: Improving keyid flexibility](tap12.md)
* [TAP 13: User Selection of the Top-Level Target Files Through Mapping Metadata](tap12.md)
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved

## Rejected

Expand Down
164 changes: 164 additions & 0 deletions tap13.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
* TAP: 13
* Title: User Selection of the Top-Level Target Files Through Mapping Metadata
Copy link
Member

@joshuagl joshuagl Dec 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Title: User Selection of the Top-Level Target Files Through Mapping Metadata
* Title: Client Selection of the Top-Level Target Files Through Mapping Metadata

I wonder if this title makes more sense?

* Version: 1
* Last-Modified: 06-Jun-2020
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
* Author: Justin Cappos, Joshua Lock, Marina Moore, Lukas Pühringer
* Status: Draft
* Content-Type: text/markdown
* Requires: TAP 4
* Created: 29-May-2020

# Abstract

This TAP discusses a means by which different users of the same repository
may elect to use different, repository-hosted, top-level targets metadata. This effectively
enables different namespaces to exist on a repository and also provides
additional resilience to attack in the case that the root keys on the
repository are compromised.



# Motivation


In TUF, it is not possible for different users to have different namespaces on
the same repository. That is, if Alice and Bob both use repository X and ask
for package foo, they will both receive the same package.
This proposal enables clients to restrict the targets they consume to
filtered views of the repository.

These different views could be defined by either different users on the
repository, made available by the repository administrator, or be created by
some other third party. One likely use is to have a repository where the signing
authority for namespaced collections of targets are delegated to more granular
roles, such as in the proposed PyPI Maximum Security Model where developers
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
sign for the targets produced by their projects. A client can curate a list of
trusted projects which is a subset of the targets on the repository by using
mapping metadata per [TAP 4](tap4.md) to only include roles they trust in their
targets metadata. One could imagine that other users (perhaps those at the
same organization) would also like to use the same curated list. These use
cases are all supported by this proposal.

There are several reasons why it may be important to let Alice and Bob's view of
the repository differ.

First, Alice and Bob may each curate different lists of packages that they
trust. For example, the security team at Alice's company has only blessed
specific packages and Alice wishes to install only those packages. Every other
user clearly should not be subject to those constraints.

Second, Alice may be concerned that a full repository compromise may include
the root role. Since the root role in TUF indicates the top-level target's
role key, this compromise can enable the attacker full control of Alice's
namespace. Alice may want to require that the security team at her company
still be used to decide which packages to trust.

Finally, in fact, Alice's company may have dictated that references to a
specific tag name should all (transparently) refer to a specific in-house
version, which may not match the result of
resolving foo using the repository's top-level targets metadata.
Instead foo should refer to the name that is resolved using Alice’s
company’s targets metadata file as the top-level targets metadata file. This may
also enable Alice to install software which is available on the repository
but would not be trusted by other users.

Note that in all of the above cases, Alice and Bob still want to use the
repository as a means to coordinate and obtain new versions of targets
metadata. They however 1) want control of what packages would be installed
and 2) want to limit the damage caused by a root key compromise on the
repository.

# Rationale

We introduce this TAP because the alternative is slightly onerous. One could
technically achieve the first and second use cases (different curated lists of
packages and additional protection against a compromise of the repository’s
root key) by using delegations to multiple repositories. The way in which this
would work would be to have the security team at Alice's company run their
own repository and for Alice to use a mapping [TAP 4](tap4.md) that indicates
that both the security team and the original repository must be trusted for an
installation to happen. In this way, only software blessed by the security team
may be installed.

However, this does not support the final use case above of transparently
referring to an in-house version. The reason is that
the original repository must also indicate that software is trustworthy, which it
would not in this case. This TAP allows the user to override (i.e., ignore) the
top-level targets metadata. The repository's separate namespace will not
match with Alice's in this case.

# Specification

In order to support this situation, we propose a change to the mapping
metadata to enable the name and key(s) for a targets metadata file to be specified.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example of the new mapping metdata might be helpful

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'm a bit at a loss about how to do this since the mapping metadata isn't precisely defined in format.

Does anyone have thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have a definition in TAP 4:

{
  // For each repository, its key name is the directory where files, including
  // the root metadata file, are cached, and its value is a list of URLs where
  // files may be downloaded.
  "repositories": {
    "Django": ["https://djangoproject.com/"],
    "PyPI":   ["https://pypi.python.org/"]
  },
  // For each set of targets, specify a list of repositories where files may be
  // downloaded.
  "mapping": [
    {
      // Much like target delegation, the order of these entries indicates
      // the priority of the delegation.  The entries listed first will be
      // considered first.
      // Map the targets "/django/django-1.*.tgz" to both Django and PyPI.
      "paths":        ["/django/django-1.*.tgz"],
      "repositories": ["Django", "PyPI"],
      // At least one repository must sign for the same length and hashes
      // of the "/django/django-1.*.tgz" targets.
      "threshold": 1
      // In this case, the "terminating" attribute is set to false.
      "terminating":  false,
      // Therefore, if this mapping has not signed for "/django/django-1.*.tgz"
      // targets, the following mapping will be consulted.
    },
    {
      ...
    {
      // Map all other targets only to PyPI.
      "paths":        ["*"],
      "repositories": ["PyPI"],
      "terminating": true
      "threshold": 1
    }
  ]
}

I'll need to think about how to best integrate TAP 13 with the concepts of TAP 4.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a bit to think through, but I don't think we expect the selection of top-level targets to be mutually exclusive of other mappings? For example, I could have a mapping file which both maps the targets role to my filtered view of targets file(s) and maps paths (that must exist within this filtered view) to repositories with optional threshold and terminating flags.

With that in mind I started to wonder about extending the existing "mapping" list to include a list of targets. A threshold flag seems to me to make sense for a targets mapping, such that a minimum number of repositories sign for the same targets metadata file(s). I think a terminating flag might also makes sense, such that a user could prevent the targets metadata file(s) being trusted from some of the mapped repositories?

However, I haven't been able to fully reason out how we would express the nuances above in the specification and workflows.

Therefore, I am wondering if it would it make more sense to have the targets mapping be a separate ordered list of targets files to include in the customised namespace? Making our mapping file something like:

{
  // For each repository, its key name is the directory where files, including
  // the root metadata file, are cached, and its value is a list of URLs where
  // files may be downloaded.
  "repositories": {
    "Django": ["https://djangoproject.com/"],
    "PyPI":   ["https://pypi.python.org/"]
  },
  // The names and keys of targets metadata files on the repository that
  // will be composed together into a filtered view of the repository for
  // this client.
  // TODO: must the targets metadata files exist on all repositories?
  "targets": {
      "tuf.json": {"keyids": [...]},
      "securesystemslib.json": {"keyids": [...]}
  },
  // For each set of targets, specify a list of repositories where files may be
  // downloaded.
  "mapping": [
    {
      // Much like target delegation, the order of these entries indicates
      // the priority of the delegation.  The entries listed first will be
      // considered first.
      // Map the targets "/django/django-1.*.tgz" to both Django and PyPI.
      "paths":        ["/django/django-1.*.tgz"],
      "repositories": ["Django", "PyPI"],
      // At least one repository must sign for the same length and hashes
      // of the "/django/django-1.*.tgz" targets.
      "threshold": 1
      // In this case, the "terminating" attribute is set to false.
      "terminating":  false,
      // Therefore, if this mapping has not signed for "/django/django-1.*.tgz"
      // targets, the following mapping will be consulted.
    },
    {
      ...
    {
      // Map all other targets only to PyPI.
      "paths":        ["*"],
      "repositories": ["PyPI"],
      "terminating": true
      "threshold": 1
    }
  ]
}

In the example above, would the targets need to exist on all repositories?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding, in that example the top-level targets file would need to exist on all repositories. If we want it to differ between repositories, maybe we can allow the user to include one for each mirror.

On another note, how would targets mapping metadata work for a client that does not support multiple repositories? One advantage to putting the targets mapping information in a separate file from the repository mapping information is that a client can choose to use one or the other of these without additional overhead.

This targets metadata file will be uploaded to the repository and will be used as though
it is the top-level targets metadata file by the client instead of the top-level targets
metadata file listed in the repository's root metadata. As is true in all TUF repositories,
all targets metadata files are listed in the snapshot file and benefit from the usual
rollback and similar protections provided.

Note that both the name and the key MUST be specified. If the name
were permitted to be specified without the key, then the repository
would be trusted to serve the correct file, without any offline key attesting
to which keys indicate the targets role.

As such, we add to the [Mechanisms that Assigns Targets to Repositories](https://github.com/theupdateframework/taps/blob/master/tap4.md#mechanism-that-assigns-targets-to-repositories)
support for a reference to the targets file in an identical way to the
root file's reference in the [TUF specification](https://github.com/theupdateframework/specification/blob/master/tuf-spec.md#4-document-formats).
However, additionally, the file name must be specified as this is no longer
targets.json.

Note that the TUF specification's discussions about metadata storage, writing,
and retrieval are not changed by this TAP. The description about how to
(optionally) write consistent snapshots is not changed by this TAP. Consistent
snapshots already require versioned metadata to be available for all targets metadata
files. All targets metadata files (top-level and otherwise) are also stored in the
same METAPATH location listed in snapshot.json.

The changes in the client application workflow are fairly minor from this
TAP. Steps 4.0 and 4.4.0 should refer to the specified target's metadata file instead
of the top-level targets metadata file. Additionally, instead of verifying the targets metadata
file using the key in the root metadata in step 4.0, verification must use the
keys listed in the mapping metadata.

There likely also needs to be a clarity pass throughout to make this potential
use mode clearer in the specification.

From an operational standpoint, a lost targets key for a delegated target could have been
remedied before by the repository but this no longer works. If the repository delegated to
a target from the top-level targets role, that file could be updated if Alice’s key changed or
was lost. However, as the repository’s root role is no longer trusted, any clients using this
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
TAP must take more care if it is operationally difficult to touch clients in the case of key
loss, perhaps first using a targets role with a threshold of offline keys before delegating to
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
a developer’s key. TAP 8 also provides support for cases where the key need to be rotated
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By developer's key, do you mean top-level targets key? It might be confusing to the reader to talk about a developer key that wasn't mentioned before here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I find it interesting to say that the client delegates to the developer (top-level targets?). If we frame it that way we could say that the mapping file and thus the client becomes the root of trust. Is that correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
a developer’s key. TAP 8 also provides support for cases where the key need to be rotated
what would have been the top-level targets role. TAP 8 also provides support for cases where the key need to be rotated

or changed and the key is still accessible to the developer.


# Security Analysis

Our overall belief is that this is a security positive change to TUF.
The added complexity from this change is fairly small. The mapping metadata
itself already exists in TUF and this TAP merely makes a small addition to
parameterize the top-level targets role. We feel that implementation errors
with adding this TAP are unlikely to occur. However, the ability to better
control trust should help users to better secure important operational use
cases. We are also unaware of plausible scenarios where this feature would
lead to insecurity due to abuse or misconfiguration. Hence our belief is that
this TAP will be a security positive change.
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved
JustinCappos marked this conversation as resolved.
Show resolved Hide resolved

# Backwards Compatibility

This TAP does not require clients that do not support this TAP to update.
Hence, all existing clients may continue to update. As the mapping metadata
is controlled on the client device, this will need to be updated along with the
client implementation. The repository metadata does not change in any way.

# Augmented Reference Implementation

[TODO: Point to a branch containing implementation of TAP 13.]

# Copyright

This document has been placed in the public domain.