From f02d060b1d19929e4050aace09f193133244f1b8 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 18 Jun 2014 18:02:50 +0200 Subject: Implement updater using TUF --- src/launcher.conf | 5 +++ src/launcher.py | 113 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 83 insertions(+), 35 deletions(-) create mode 100644 src/launcher.conf diff --git a/src/launcher.conf b/src/launcher.conf new file mode 100644 index 0000000..7cc0043 --- /dev/null +++ b/src/launcher.conf @@ -0,0 +1,5 @@ +[General] +updater_delay = 60 + +[Mirror.localhost] +url_prefix = http://localhost:8001 diff --git a/src/launcher.py b/src/launcher.py index 2a43e54..9eb5bc1 100644 --- a/src/launcher.py +++ b/src/launcher.py @@ -1,47 +1,99 @@ import os +import shutil import platform import time import threading import ConfigParser from leap.bitmask.app import main as bitmask_client -from leap.common.events import server - -from thandy.ClientCLI import update as thandy_update +from leap.common.events import server, signal +from leap.common.events import events_pb2 as proto +import tuf.client.updater bundles_per_platform = { - "Windows": "/bundleinfo/LEAPClient-win/", - "Darwin": "", - "Linux": "/bundleinfo/LEAPClient/", + "Windows": "windows", + "Darwin": "darwin", + "Linux": "linux", } GENERAL_SECTION = "General" -UPDATES_KEY = "Updates" +DELAY_KEY = "updater_delay" + + +class TUF(threading.Thread): + def __init__(self, config): + """ + Initialize the list of mirrors, paths and other TUF dependencies from the config file + """ + if config.has_section(GENERAL_SECTION) and \ + config.has_option(GENERAL_SECTION, DELAY_KEY): + self.delay = config.getboolean(GENERAL_SECTION, DELAY_KEY) + else: + self.delay = 60 + + self._load_mirrors(config) + if not self.mirrors: + print "ERROR: No updater mirrors found (missing or not well formed launcher.conf)" + self.bundle_path = os.getcwd() + self.source_path = self.bundle_path + self.dest_path = os.path.join(self.bundle_path, 'tmp') + self.update_path = os.path.join(self.bundle_path, 'updates') + + threading.Thread.__init__(self) -class Thandy(threading.Thread): def run(self): + """ + Check for updates periodically + """ + if not self.mirrors: + return + while True: try: - os.environ["THANDY_HOME"] = os.path.join(os.getcwd(), - "config", - "thandy") - os.environ["THP_DB_ROOT"] = os.path.join(os.getcwd(), - "packages") - os.environ["THP_INSTALL_ROOT"] = os.path.join(os.getcwd(), - "updates") - args = [ - "--repo=repo/", - "--install", - bundles_per_platform[platform.system()] - ] - thandy_update(args) + tuf.conf.repository_directory = os.path.join(self.bundle_path, 'repo') + + updater = tuf.client.updater.Updater('leap-updater', self.mirrors) + updater.refresh() + + targets = updater.all_targets() + updated_targets = updater.updated_targets(targets, self.source_path) + for target in updated_targets: + updater.download_target(target, self.dest_path) + self._set_permissions(target) + if os.path.isdir(self.dest_path): + if os.path.isdir(self.update_path): + shutil.rmtree(self.update_path) + shutil.move(self.dest_path, self.update_path) + signal(proto.UPDATER_NEW_UPDATES, + content=", ".join(sorted([f['filepath'] for f in updated_targets]))) + return except Exception as e: print "ERROR:", e finally: - # TODO: Make this delay configurable - time.sleep(60) + time.sleep(self.delay) + + def _load_mirrors(self, config): + self.mirrors = {} + for section in config.sections(): + if section[:6] != 'Mirror': + continue + url_prefix = config.get(section, 'url_prefix') + metadata_path = bundles_per_platform[platform.system()] + '/metadata' + targets_path = bundles_per_platform[platform.system()] + '/targets' + self.mirrors[section[7:]] = {'url_prefix': url_prefix, + 'metadata_path': metadata_path, + 'targets_path': targets_path, + 'confined_target_dirs': ['']} + + def _set_permissions(self, target): + file_permisions = int(target["fileinfo"]["custom"]["file_permissions"], 8) + filepath = target['filepath'] + if filepath[0] == '/': + filepath = filepath[1:] + file_path = os.path.join(self.dest_path, filepath) + os.chmod(file_path, file_permisions) if __name__ == "__main__": @@ -50,17 +102,8 @@ if __name__ == "__main__": config = ConfigParser.ConfigParser() config.read("launcher.conf") - launch_thandy = False - - has_config = config.has_section(GENERAL_SECTION) and \ - config.has_option(GENERAL_SECTION, UPDATES_KEY) - - if has_config: - launch_thandy = config.getboolean(GENERAL_SECTION, UPDATES_KEY) - - if launch_thandy: - thandy_thread = Thandy() - thandy_thread.daemon = True - thandy_thread.start() + tuf_thread = TUF(config) + tuf_thread.daemon = True + tuf_thread.start() bitmask_client() -- cgit v1.2.3