Address review of pr#580 (Revise API for delegating paths)
This commit is contained in:
Vladimir Diaz 2018-01-19 16:19:09 -05:00 committed by GitHub
commit fec88be847
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 57 deletions

View file

@ -1460,17 +1460,17 @@ def test_add_paths(self):
self.targets_object.delegate(rolename, public_keys, [], threshold,
list_of_targets=None, path_hash_prefixes=None)
# Delegate an extra role for test coverage (i.e., check that restricted
# paths are not added to a child role not requested.)
# Delegate an extra role for test coverage (i.e., to later verify that
# delegated paths are not added to a child role that was not requested).
self.targets_object.delegate('junk_role', public_keys, [])
restricted_path = os.path.join(self.targets_directory, 'tuf_files')
os.mkdir(restricted_path)
paths = [restricted_path + '/*']
delegated_path = os.path.join(self.targets_directory, 'tuf_files')
os.mkdir(delegated_path)
paths = [delegated_path + '/*']
self.targets_object.add_paths(paths, 'tuf')
# Retrieve 'targets_object' roleinfo, and verify the roleinfo contains
# the expected restricted paths of the delegated role. Only
# Retrieve 'targets_object' roleinfo, and verify the roleinfo contains the
# expected delegated paths of the delegated role.
targets_object_roleinfo = tuf.roledb.get_roleinfo(self.targets_object.rolename,
'test_repository')

View file

@ -12,7 +12,7 @@
- [Managing Targets](#managing_targets)
<a name="overview">
## Overview
## Overview
The Update Framework (TUF) is a Python-based security system for software
updates. In order to prevent your users from downloading vulnerable or malicious
code disguised as updates to your software, TUF requires that each update you
@ -56,7 +56,7 @@ is the private key.
>>> generate_and_write_rsa_keypair("path/to/key")
Enter a password for the RSA key:
Confirm:
>>>
>>>
```
We can also use the bits parameter to set a different key length (the default
@ -131,7 +131,7 @@ public key by the server (upon uploading) and by the clients (when updating).
<a name="signing_and_writing_the_metadata">
### Signing and Writing the Metadata ###
In order to sign the metadata, we need to import the private key corresponding
In order to sign the metadata, we need to import the private key corresponding
to the public key we added to the project. One the key is loaded to the project,
it will automatically be used to sign the metadata whenever it is written.
@ -160,14 +160,14 @@ several contributors, you may want to consider adding
<a name="loading_an_existing_project">
## Loading an Existing Project
To make changes to existing metadata, we will need the Project again. We can
restore it with the load_project() function.
To make changes to existing metadata, we will need the Project again. We can
restore it with the load_project() function.
```
>>> from tuf.developer_tool import *
>>> project = load_project("local/path/to/metadata")
```
Each time the project is loaded anew, the necessary private keys must also be
Each time the project is loaded anew, the necessary private keys must also be
loaded in order to sign metadata.
```
@ -205,21 +205,21 @@ contain any number of public keys. We can also add keys to the role after
creating it using the [add\_verification\_key()](#adding_a_key_to_a_delegation)
method.
### Restricted Paths
### Delegated Paths
By default, a delegated role is permitted to add and modify targets anywhere in
the Project's targets directory. We can assign restricted paths to a delegated
role to limit this permission.
the Project's targets directory. We can delegate trust of paths to a role to
limit this permission.
```
>>> project.add_restricted_paths(["restricted/filepath"], "newrole")
>>> project.add_paths(["delegated/filepath"], "newrole")
```
This will prevent the delegated role from signing targets whose local filepaths
do not begin with "restricted/filepath". We can assign several restricted
filepaths to a role by adding them to the list in the first parameter, or by
invoking the method again. A role with multiple restricted paths can add
targets to any of them.
do not begin with "delegated/filepath". We can delegate several filepaths to a
role by adding them to the list in the first parameter, or by invoking the
method again. A role with multiple delegated paths can add targets to any of
them.
Note that this method is invoked from the parent role (in this case, the Project)
and takes the delegated role name as an argument.
@ -248,16 +248,16 @@ Delegations can be revoked, removing the delegated role from the project.
```
<a name="managing_keys">
## Managing Keys
## Managing Keys
This section describes the key-related functions and parameters not covered in
the [Creating a Simple Project](#creating_a_simple_project) section.
### Additional Parameters for Key Generation
When generating keys, it is possible to specify the length of the key in bits
When generating keys, it is possible to specify the length of the key in bits
and its password as parameters:
```
>>> generate_and_write_rsa_keypair("path/to/key",bits=2048, password="pw")
>>> generate_and_write_rsa_keypair("path/to/key", bits=2048, password="pw")
```
The bits parameter defaults to 3072, and values below 2048 will raise an error.
The password parameter is only intended to be used in scripts.

View file

@ -585,9 +585,9 @@ The `delegate_hashed_bins()` method has the following form:
delegate_hashed_bins(list_of_targets, keys_of_hashed_bins, number_of_bins)
```
A complete example of retrieving target paths to add to hashed bins,
performing the hashed bin delegations, signing them, and finally adding
restricted paths for some role is provided next.
We next provide a complete example of retrieving target paths to add to hashed
bins, performing the hashed bin delegations, signing them, and delegating paths
to some role.
```Python
# Get a list of target paths for the hashed bins.
>>> targets = \

View file

@ -1765,12 +1765,12 @@ def target_files(self):
def add_paths(self, paths, child_rolename):
"""
<Purpose>
Add 'paths' to the delegated paths for 'child_rolename'. 'paths' can be
a list of either file paths or glob patterns. The updater client
verifies the target paths specified by child roles, and searches for
targets by visiting these delegated paths. A child role may only provide
targets specifically listed in the delegations field of the parent role,
or a target that matches a delegated path.
Add 'paths' to the delegated paths of 'child_rolename'. 'paths' can be a
list of either file paths or glob patterns. The updater client verifies
the target paths specified by child roles, and searches for targets by
visiting these delegated paths. A child role may only provide targets
specifically listed in the delegations field of the delegating role, or a
target that matches a delegated path.
>>>
>>>
@ -1787,8 +1787,12 @@ def add_paths(self, paths, child_rolename):
'Django' in 'unclaimed').
<Exceptions>
securesystemslib.exceptions.Error, if a path or glob pattern in 'paths'
is not a string, or if 'child_rolename' has not been delegated yet.
securesystemslib.exceptions.FormatError, if a path or glob pattern in
'paths' is not a string, or if 'child_rolename' is not a formatted
rolename.
securesystemslib.exceptions.Error, if 'child_rolename' has not been
delegated yet.
<Side Effects>
Modifies this Targets' delegations field.
@ -1797,7 +1801,7 @@ def add_paths(self, paths, child_rolename):
None.
"""
# Does 'filepath' have the correct format?
# Do the argument have the correct format?
# Ensure the arguments have the appropriate number of objects and object
# types, and that all dict keys are properly named.
# Raise 'securesystemslib.exceptions.FormatError' if there is a mismatch.
@ -1817,9 +1821,8 @@ def add_paths(self, paths, child_rolename):
for path in paths:
# Are the delegated paths or glob patterns located in the repository's
# targets directory? If so, log it - the paths don't necessarily need to
# be located in the repository's directory.
# Append a trailing path separator with
# os.path.join(path, '').
# be located in the repository's directory. Append a trailing path
# separator with os.path.join(path, '').
targets_directory = os.path.join(self._targets_directory, '')
if not path.startswith(targets_directory):
logger.debug(repr(path) + ' is not located in the'
@ -1835,14 +1838,14 @@ def add_paths(self, paths, child_rolename):
# Update the delegated paths of 'child_rolename' to add relative paths.
for role in roleinfo['delegations']['roles']:
if role['name'] == child_rolename:
delegated_paths = role['paths']
for relative_path in relative_paths:
if relative_path not in delegated_paths:
delegated_paths.append(relative_path)
for relative_path in relative_paths:
if relative_path not in role['paths']:
role['paths'].append(relative_path)
else:
logger.debug(repr(relative_path) + ' is already a delegated path.')
else:
logger.debug(repr(relative_path) + ' is already a delegated path.')
logger.debug(repr(role['name']) + ' does not match child rolename.')
tuf.roledb.update_roleinfo(self._rolename, roleinfo,
repository_name=self._repository_name)
@ -2157,8 +2160,11 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
paths:
The paths, or glob patterns, delegated to 'rolename'. Any targets
added to 'rolename' must match one of the paths or glob patterns in
'paths'.
added to 'rolename', via add_targets() or 'list_of_targets', must
match one of the paths or glob patterns in 'paths'. Apart from the
public keys of 'rolename', the delegated 'paths' is often known and
specified when a delegation is first performed. If the delegator
is unsure of which 'paths' to delegate, 'paths' can be set to [''].
threshold:
The threshold number of keys of 'rolename'.
@ -2175,7 +2181,7 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
file specified by 'target/other_role'.
list_of_targets:
A list of target filepaths that are added to the paths of 'rolename'.
A list of target filepaths that are added to 'rolename'.
'list_of_targets' is a list of target filepaths, can be empty, and each
filepath must be located in the repository's targets directory. The
list of targets should also exist at the specified paths, otherwise
@ -2261,14 +2267,13 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
# targets directory.
relative_paths = []
if paths is not None:
for path in paths:
if not path.startswith(self._targets_directory + os.sep):
logger.debug(repr(path) + ' is not loated in the repository\'s'
' targets directory: ' + repr(self._targets_directory))
for path in paths:
if not path.startswith(self._targets_directory + os.sep):
logger.debug(repr(path) + ' is not loated in the repository\'s'
' targets directory: ' + repr(self._targets_directory))
# Append a trailing path separator with os.path.join(path, '').
relative_paths.append(path[targets_directory_length:])
# Append a trailing path separator with os.path.join(path, '').
relative_paths.append(path[targets_directory_length:])
# Create a new Targets object for the 'rolename' delegation. An initial
# expiration is set (3 months from the current time).
@ -2299,10 +2304,10 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
'terminating': terminating,
'paths': list(roleinfo['paths'].keys())}
if paths is not None:
if paths:
roleinfo['paths'] = relative_paths
if path_hash_prefixes is not None:
if path_hash_prefixes:
roleinfo['path_hash_prefixes'] = path_hash_prefixes
# A role in a delegations must list either 'path_hash_prefixes'
# or 'paths'.