mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
- "quickstart.py:292: No global (EEXIST) found" - "basic_client.py:194: No global (option_parser) found" - "rsa_key.py:108: No global (EnvelopeError) found" - "rsa_key.py:108: No global (KeygenError) found" - "util.py:56: No global (temp_dir) found"
215 lines
6.8 KiB
Python
Executable file
215 lines
6.8 KiB
Python
Executable file
"""
|
|
<Program Name>
|
|
basic_client.py
|
|
|
|
<Author>
|
|
Vladimir Diaz <vladimir.v.diaz@gmail.com>
|
|
|
|
<Started>
|
|
September 2012
|
|
|
|
<Copyright>
|
|
See LICENSE for licensing information.
|
|
|
|
<Purpose>
|
|
Provide a basic TUF client that can update all of the metatada and target
|
|
files provided by the user-specified repository mirror. Updated files are
|
|
saved to the 'targets' directory in the current working directory. The
|
|
repository mirror is specified by the user through the '--repo' command-
|
|
line option.
|
|
|
|
Normally, a software updater integrating TUF will develop their own costum
|
|
client module by importing 'tuf.client.updater', instantiating the required
|
|
object, and calling the desired methods to perform an update. This basic
|
|
client is provided to users who wish to give TUF a quick test run without
|
|
the hassle of writing client code. This module can also used by updaters that
|
|
do not need the customization and only require their clients to perform an
|
|
update of all the files provided by their repository mirror(s).
|
|
|
|
For software updaters that DO require customization, see the 'example_client.py'
|
|
script. The 'example_client.py' script provides an outline of the client code
|
|
that software updaters may develop and then tailor to their specific software
|
|
updater or package manager.
|
|
|
|
Additional tools for clients running legacy applications will also be made
|
|
available. These tools will allow secure software updates using The Update
|
|
Framework without the need to modify the original application.
|
|
|
|
<Usage>
|
|
$ python basic_client.py --repo http://localhost:8001
|
|
$ python basic_client.py --repo http://localhost:8001 --verbose 3
|
|
|
|
<Options>
|
|
--verbose:
|
|
Set the verbosity level of logging messages. Accepts values 1-5.
|
|
|
|
--repo:
|
|
Set the repository mirror that will be responding to client requests.
|
|
E.g., 'http://locahost:8001'.
|
|
|
|
"""
|
|
|
|
import sys
|
|
import optparse
|
|
import logging
|
|
|
|
import tuf.client.updater
|
|
import tuf.log
|
|
|
|
# See 'log.py' to learn how logging is handled in TUF.
|
|
logger = logging.getLogger('tuf.basic_client')
|
|
|
|
|
|
def update_client(repository_mirror):
|
|
"""
|
|
<Purpose>
|
|
Perform an update of the metadata and target files located at
|
|
'repository_mirror'. Target files are saved to the 'targets' directory
|
|
in the current working directory. The current directory must already
|
|
include a 'metadata' directory, which in turn must contain the 'current'
|
|
and 'previous' directories. At a minimum, these two directories require
|
|
the 'root.txt' metadata file.
|
|
|
|
<Arguments>
|
|
repository_mirror:
|
|
The URL to the repository mirror hosting the metadata and target
|
|
files. E.g., 'http://localhost:8001'
|
|
|
|
<Exceptions>
|
|
tuf.RepositoryError, if 'repository_mirror' is improperly formatted.
|
|
|
|
<Side Effects>
|
|
Connects to a repository mirror and updates the metadata files and
|
|
any target files. Obsolete targets are also removed locally.
|
|
|
|
<Returns>
|
|
None.
|
|
|
|
"""
|
|
|
|
# Does 'repository_mirror' have the correct format?
|
|
try:
|
|
tuf.formats.URL_SCHEMA.check_match(repository_mirror)
|
|
except tuf.FormatError, e:
|
|
message = 'The repository mirror supplied is invalid.'
|
|
raise tuf.RepositoryError(message)
|
|
|
|
# Set the local repository directory containing all of the metadata files.
|
|
tuf.conf.repository_directory = '.'
|
|
|
|
# Set the repository mirrors. This dictionary is needed by the Updater
|
|
# class of updater.py.
|
|
repository_mirrors = {'mirror': {'url_prefix': repository_mirror,
|
|
'metadata_path': 'metadata',
|
|
'targets_path': 'targets',
|
|
'confined_target_dirs': ['']}}
|
|
|
|
# Create the repository object using the repository name 'repository'
|
|
# and the repository mirrors defined above.
|
|
updater = tuf.client.updater.Updater('repository', repository_mirrors)
|
|
|
|
# The local destination directory to save the target files.
|
|
destination_directory = './targets'
|
|
|
|
# Refresh the repository's top-level roles, store the target information for
|
|
# all the targets tracked, and determine which of these targets have been
|
|
# updated.
|
|
updater.refresh()
|
|
all_targets = updater.all_targets()
|
|
updated_targets = updater.updated_targets(all_targets, destination_directory)
|
|
|
|
# Download each of these updated targets and save them locally.
|
|
for target in updated_targets:
|
|
try:
|
|
updater.download_target(target, destination_directory)
|
|
except tuf.DownloadError, e:
|
|
pass
|
|
|
|
# Remove any files from the destination directory that are no longer being
|
|
# tracked.
|
|
updater.remove_obsolete_targets(destination_directory)
|
|
|
|
|
|
|
|
|
|
|
|
def parse_options():
|
|
"""
|
|
<Purpose>
|
|
Parse the command-line options and set the logging level
|
|
as specified by the user through the --verbose option.
|
|
'basic_client' expects the '--repo' to be set by the user.
|
|
|
|
Example:
|
|
$ python basic_client.py --repo http://localhost:8001
|
|
|
|
If the required option is unset, a parser error is printed
|
|
and the scripts exits.
|
|
|
|
<Arguments>
|
|
None.
|
|
|
|
<Exceptions>
|
|
None.
|
|
|
|
<Side Effects>
|
|
Sets the logging level for TUF logging.
|
|
|
|
<Returns>
|
|
The 'options.REPOSITORY_MIRROR' string.
|
|
|
|
"""
|
|
|
|
parser = optparse.OptionParser()
|
|
|
|
# Add the options supported by 'basic_client' to the option parser.
|
|
parser.add_option('--verbose', dest='VERBOSE', type=int, default=2,
|
|
help='Set the verbosity level of logging messages.'
|
|
'The lower the setting, the greater the verbosity.')
|
|
|
|
parser.add_option('--repo', dest='REPOSITORY_MIRROR', type='string',
|
|
help='Specifiy the repository mirror\'s URL prefix '
|
|
'(e.g., http://www.example.com:8001/tuf/).'
|
|
' The client will download updates from this mirror.')
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
# Set the logging level.
|
|
if options.VERBOSE == 5:
|
|
tuf.log.set_log_level(logging.CRITICAL)
|
|
elif options.VERBOSE == 4:
|
|
tuf.log.set_log_level(logging.ERROR)
|
|
elif options.VERBOSE == 3:
|
|
tuf.log.set_log_level(logging.WARNING)
|
|
elif options.VERBOSE == 2:
|
|
tuf.log.set_log_level(logging.INFO)
|
|
elif options.VERBOSE == 1:
|
|
tuf.log.set_log_level(logging.DEBUG)
|
|
else:
|
|
tuf.log.set_log_level(logging.NOTSET)
|
|
|
|
# Ensure the '--repo' option was set by the user.
|
|
if options.REPOSITORY_MIRROR is None:
|
|
message = '"--repo" must be set on the command-line.'
|
|
parser.error(message)
|
|
|
|
# Return the repository mirror containing the metadata and target files.
|
|
return options.REPOSITORY_MIRROR
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
# Parse the options and set the logging level.
|
|
repository_mirror = parse_options()
|
|
|
|
# Perform an update of all the files in the 'targets' directory located in
|
|
# the current directory.
|
|
try:
|
|
update_client(repository_mirror)
|
|
except tuf.RepositoryError, e:
|
|
sys.stderr.write(str(e)+'\n')
|
|
sys.exit(1)
|
|
|
|
# Successfully updated the client's target files.
|
|
sys.exit(0)
|