Make confined_target_dirs optional field

The field confined_target_dirs from the MIRROR_SCHEMA  is
a list of strings. Those strings define the accessible target
paths for that mirror. For one target to be available for that mirror,
its path should have as a prefix at least one of the strings defined
in confined_target_dirs.

That's why when confined_target_dirs is a list with one element empty
string (e.g. ['']) this means all targets files on that mirror are
available and if confined_target_dirs is empty list (e.g. []) this
would be interpreted as none of the target files is available.

This is a confusing API that could easily lead to mistakes.
That's why it's better we promote to not set confined_target_dirs
at all if a user wants targets to be available.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
This commit is contained in:
Martin Vrachev 2020-10-05 14:46:14 +03:00
parent a64a334cd4
commit 946d11bca4
18 changed files with 38 additions and 51 deletions

View file

@ -132,8 +132,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -134,8 +134,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -141,8 +141,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -261,6 +261,12 @@ def test_schemas(self):
'confined_target_dirs': ['path1/', 'path2/'],
'custom': {'type': 'mirror'}}),
'MIRROR_SCHEMA_NO_CONFINED_TARGETS': (tuf.formats.MIRROR_SCHEMA,
{'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',
'targets_path': 'targets/',
'custom': {'type': 'mirror'}}),
'MIRRORDICT_SCHEMA': (tuf.formats.MIRRORDICT_SCHEMA,
{'mirror1': {'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',

View file

@ -148,8 +148,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -141,8 +141,7 @@ def setUp(self):
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Creating repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -50,8 +50,7 @@ def setUp(self):
self.mirrors = \
{'mirror1': {'url_prefix' : 'http://mirror1.com',
'metadata_path' : 'metadata',
'targets_path' : 'targets',
'confined_target_dirs' : ['']},
'targets_path' : 'targets'},
'mirror2': {'url_prefix' : 'http://mirror2.com',
'metadata_path' : 'metadata',
'targets_path' : 'targets',

View file

@ -140,8 +140,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -151,13 +151,11 @@ def setUp(self):
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
self.repository_mirrors2 = {'mirror1': {'url_prefix': url_prefix2,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instances. The test cases will use these client
# updaters to refresh metadata, fetch target files, etc.

View file

@ -140,8 +140,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -217,8 +217,7 @@ def setUp(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Create the repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -170,8 +170,7 @@ def setUp(self):
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Creating a repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.
@ -1092,8 +1091,7 @@ def test_6_get_one_valid_targetinfo(self):
+ str(self.server_process_handler.port) + repository_basepath
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
# Creating a repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.
@ -1391,8 +1389,7 @@ def test_7_updated_targets(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
# Creating a repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.
@ -1519,8 +1516,7 @@ def test_8_remove_obsolete_targets(self):
tuf.settings.repositories_directory = self.client_directory
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
# Creating a repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.
@ -1890,12 +1886,10 @@ def setUp(self):
url_prefix2 = 'http://localhost:' + str(self.SERVER_PORT2)
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
self.repository_mirrors2 = {'mirror1': {'url_prefix': url_prefix2,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
# Create the repository instances. The test cases will use these client
# updaters to refresh metadata, fetch target files, etc.

View file

@ -149,8 +149,7 @@ def setUp(self):
self.repository_mirrors = {'mirror1': {'url_prefix': url_prefix,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# Creating a repository instance. The test cases will use this client
# updater to refresh metadata, fetch target files, etc.

View file

@ -63,15 +63,14 @@ tuf.settings.repositories_directory = 'path/to/local_repository'
# and targets files can be found in the 'metadata' and 'targets' directory,
# respectively. If the client wishes to only download target files from
# specific directories on the mirror, the 'confined_target_dirs' field
# should be set. In the example, the client has chosen '', which is
# interpreted as no confinement. In other words, the client can download
# should be set. In this example, the client hasn't set confined_target_dirs,
# which is interpreted as no confinement. In other words, the client can download
# targets from any directory or subdirectories. If the client had chosen
# 'targets1/', they would have been confined to the '/targets/targets1/'
# directory on the 'http://localhost:8001' mirror.
repository_mirrors = {'mirror1': {'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# The updater may now be instantiated. The Updater class of 'updater.py'
# is called with two arguments. The first argument assigns a name to this

View file

@ -68,15 +68,15 @@
# and targets files can be found in the 'metadata' and 'targets' directory,
# respectively. If the client wishes to only download target files from
# specific directories on the mirror, the 'confined_target_dirs' field
# should be set. In the example, the client has chosen '', which is
# interpreted as no confinement. In other words, the client can download
# should be set. In this example, the client hasn't set confined_target_dirs,
# which is interpreted as no confinement.
# In other words, the client can download
# targets from any directory or subdirectories. If the client had chosen
# 'targets1/', they would have been confined to the '/targets/targets1/'
# directory on the 'http://localhost:8001' mirror.
repository_mirrors = {'mirror1': {'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}}
'targets_path': 'targets'}}
# The updater may now be instantiated. The Updater class of 'updater.py'
# is called with two arguments. The first argument assigns a name to this
@ -504,8 +504,7 @@ def get_updater(self, repository_name):
mirrors[url] = {
'url_prefix': url,
'metadata_path': 'metadata',
'targets_path': 'targets',
'confined_target_dirs': ['']}
'targets_path': 'targets'}
try:
# NOTE: State (e.g., keys) should NOT be shared across different

View file

@ -405,7 +405,7 @@
url_prefix = securesystemslib.formats.URL_SCHEMA,
metadata_path = SCHEMA.Optional(RELPATH_SCHEMA),
targets_path = SCHEMA.Optional(RELPATH_SCHEMA),
confined_target_dirs = RELPATHS_SCHEMA,
confined_target_dirs = SCHEMA.Optional(RELPATHS_SCHEMA),
custom = SCHEMA.Optional(SCHEMA.Object()))
# A dictionary of mirrors where the dict keys hold the mirror's name and

View file

@ -112,8 +112,10 @@ def get_list_of_mirrors(file_type, file_path, mirrors_dict):
# for targets, ensure directory confinement
if path_key == 'targets_path':
full_filepath = os.path.join(path, file_path)
if not in_confined_directory(full_filepath,
mirror_info['confined_target_dirs']):
confined_target_dirs = mirror_info.get('confined_target_dirs')
# confined_target_dirs is an optional field
if confined_target_dirs and not in_confined_directory(full_filepath,
confined_target_dirs):
continue
# urllib.quote(string) replaces special characters in string using the %xx

View file

@ -117,8 +117,7 @@ def update_client(parsed_arguments):
# Set the repository mirrors. This dictionary is needed by the Updater
# class of updater.py.
repository_mirrors = {'mirror': {'url_prefix': parsed_arguments.repo,
'metadata_path': 'metadata', 'targets_path': 'targets',
'confined_target_dirs': ['']}}
'metadata_path': 'metadata', 'targets_path': 'targets'}}
# Create the repository object using the repository name 'repository'
# and the repository mirrors defined above.