-
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
TAP13 draft #118
TAP13 draft #118
Changes from 5 commits
5594292
eec0076
8c0ef12
cc692d4
3c90fa2
0de3dc8
64302b0
caefc43
eaaddf7
7b3e67a
ac6bce2
7cca85a
116842a
a31e535
6d480ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,165 @@ | ||||||
* TAP: 13 | ||||||
* Title: User Selection of the Top-Level Target Files Through Mapping Metadata | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
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](https://www.python.org/dev/peps/pep-0480/) where developers | ||||||
sign for the targets produced by their projects. A client can curate a list of | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is PyPI the prime example of where this could be used? I'm asking because I've been trying very hard to imagine how that would work and I've failed to identify a scenario where this would be useful. Is is possible to get a practical example (doesn't have to be in this draft) of the sort of mapping that would be useful in the PyPI case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the PEP 480 model, a user could limit PyPI downloads to those that are delegated from the claimed role, and so only install end-to-end signed images. There were also some requests for this feature with regards to container registries, so that an organization could curate a list of verified packages and keys for their customers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to write a specific example out in more detail? The core issue I have in understanding this is that people don't install stand-alone "images" from PyPI. They install a whole tree of dependencies. That tree is extremely unlikely to consist of packages signed by one or even a few roles (assuming I've understood the ideas correctly). So installing a package that depends on a dozen other packages (that in turn depend on dozens of other packages) is the norm, not the exception... and I don't think it's reasonable to assume that these packages come from only a few delegated roles. So how does the Mapping that is useful for this use case get generated in practice? Does it contain dozens of roles? What happens when the dependency tree inevitably changes and roles need to be added/removed? Maybe I've just misunderstood the idea -- but again, a specific example in the style of "company X has done due diligence on the Django developers and wants to trust them, but not pypi in general. The write a Mapping that..." could maybe help with that.
Now this seems like a much easier example to understand. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the new text here help? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right I see: the user does not curate who they trust, other than trust all developers who sign their packages and do not trust any developers who don't sign -- this seems understandable and realistic. |
||||||
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. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An example of the new mapping metdata might be helpful There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
In the example above, would the targets need to exist on all repositories? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 because the root metadata may not be used to revoke trust in | ||||||
the targets key. Thus, a user should take into account the operational difficultly to touch | ||||||
clients in the case of key loss for the top level targets file. If it is operationally difficult to | ||||||
touch the clients, then the client may perhaps use a threshold of offline keys before delegating to | ||||||
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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 except the inability to | ||||||
have the root role rotate the targets key. However, selectively removing this | ||||||
capability from the root role is the purpose of this TAP. | ||||||
|
||||||
# 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. |
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.