def _refresh_signing_keymgr(self): # Refresh key manager metadata self._key_mgr_filename = "key_mgr.json" # TODO (AV): make this a constant or config value self._key_mgr = None key_mgr_path = join(context.av_data_dir, self._key_mgr_filename) try: untrusted_key_mgr = fetch_channel_signing_data( context.signing_metadata_url_base, self._key_mgr_filename) verify_trust_delegation("key_mgr", untrusted_key_mgr, self._trusted_root) self._key_mgr = untrusted_key_mgr write_trust_metadata_to_file(self._key_mgr, key_mgr_path) except ( ConnectionError, HTTPError, ) as err: log.warn( f"Could not retrieve {self.channel.base_url}/{self._key_mgr_filename}: {err}" ) # TODO (AV): much more sensible error handling here except Exception as err: log.error(err) # If key_mgr is unavailable from server, fall back to copy on disk if self._key_mgr is None and exists(key_mgr_path): self._key_mgr = load_trust_metadata_from_file(key_mgr_path)
def _refresh_signing_root(self): # TODO (AV): formalize paths for `*.root.json` and `key_mgr.json` on server-side self._trusted_root = INITIAL_TRUST_ROOT # Load current trust root metadata from filesystem latest_root_id, latest_root_path = -1, None for cur_path in iglob(join(context.av_data_dir, "[0-9]*.root.json")): # TODO (AV): better pattern matching in above glob cur_id = basename(cur_path).split(".")[0] if cur_id.isdigit(): cur_id = int(cur_id) if cur_id > latest_root_id: latest_root_id, latest_root_path = cur_id, cur_path if latest_root_path is None: log.debug(f"No root metadata in {context.av_data_dir}. " "Using built-in root metadata.") else: log.info(f"Loading root metadata from {latest_root_path}.") self._trusted_root = load_trust_metadata_from_file( latest_root_path) # Refresh trust root metadata attempt_refresh = True while attempt_refresh: # TODO (AV): caching mechanism to reduce number of refresh requests next_version_of_root = 1 + self._trusted_root['signed']['version'] next_root_fname = str(next_version_of_root) + '.root.json' next_root_path = join(context.av_data_dir, next_root_fname) try: update_url = f"{self.channel.base_url}/{next_root_fname}" log.info( f"Fetching updated trust root if it exists: {update_url}") # TODO (AV): support fetching root data with credentials untrusted_root = fetch_channel_signing_data( context.signing_metadata_url_base, next_root_fname) verify_trust_root(self._trusted_root, untrusted_root) # New trust root metadata checks out self._trusted_root = untrusted_root write_trust_metadata_to_file(self._trusted_root, next_root_path) # TODO (AV): more error handling improvements (?) except (HTTPError, ) as err: # HTTP 404 implies no updated root.json is available, which is # not really an "error" and does not need to be logged. if err.response.status_code not in (404, ): log.error(err) attempt_refresh = False except Exception as err: log.error(err) attempt_refresh = False