def download_and_sign_file(self, task_id, run_id, url, checksum, cert_type, signing_formats, work_dir): # TODO: better parsing filename = urlparse.urlsplit(url).path.split("/")[-1] abs_filename = os.path.join(work_dir, filename) log.debug("Downloading %s", url) r = requests.get(url, timeout=60) r.raise_for_status() with open(abs_filename, 'wb') as fd: for chunk in r.iter_content(4096): fd.write(chunk) log.debug("Done") got_checksum = get_hash(abs_filename) log.info("SHA512SUM: %s URL: %s", got_checksum, url) log.info("SHA1SUM: %s URL: %s", get_hash(abs_filename, "sha1"), url) if not got_checksum == checksum: msg = "CHECKSUM MISMATCH: Expected {}, got {} for {}".format( checksum, got_checksum, url) log.debug(msg) raise ChecksumMismatchError(msg) log.debug("Signing %s", filename) self.sign_file(work_dir, filename, cert_type, signing_formats) self.create_artifact(task_id, run_id, "public/env/%s" % filename, abs_filename) detached_signatures = [] for s_type, s_ext, s_mime in get_detached_signatures(signing_formats): d_filename = "{filename}{ext}".format(filename=filename, ext=s_ext) d_abs_filename = os.path.join(work_dir, d_filename) self.create_artifact(task_id, run_id, "public/env/%s" % d_filename, d_abs_filename, content_type=s_mime) detached_signatures.append((s_type, d_filename)) return abs_filename, detached_signatures
def sign(self, task_id, run_id, task, work_dir): payload = task["payload"] manifest_url = payload["signingManifest"] signing_manifest = self.get_manifest(manifest_url) # TODO: better way to extract filename url_prefix = "/".join(manifest_url.split("/")[:-1]) cert_type = task_cert_type(task) signing_formats = task_signing_formats(task) for e in signing_manifest: # Fallback to "mar" if "file_to_sign" is not specified file_to_sign = e.get("file_to_sign", e["mar"]) file_url = "{}/{}".format(url_prefix, file_to_sign) abs_filename, detached_signatures = self.download_and_sign_file( task_id, run_id, file_url, e["hash"], cert_type, signing_formats, work_dir) # Update manifest data with new values e["hash"] = get_hash(abs_filename) e["size"] = os.path.getsize(abs_filename) e["detached_signatures"] = {} for sig_type, sig_filename in detached_signatures: e["detached_signatures"][sig_type] = sig_filename manifest_file = os.path.join(work_dir, "manifest.json") with open(manifest_file, "wb") as f: json.dump(signing_manifest, f, indent=2, sort_keys=True) log.debug("Uploading manifest for t: %s, r: %s", task_id, run_id) self.create_artifact(task_id, run_id, "public/env/manifest.json", manifest_file, "application/json")
def sign_file(self, work_dir, from_, cert_type, signing_formats, to=None): if to is None: to = from_ token = os.path.join(work_dir, "token") nonce = os.path.join(work_dir, "nonce") self.get_token(token, cert_type, signing_formats) signtool = os.path.join(self.tools_checkout, "release/signing/signtool.py") cmd = [signtool, "-n", nonce, "-t", token, "-c", self.cert] for s in self.get_suitable_signing_servers(cert_type, signing_formats): cmd.extend(["-H", s.server]) for f in signing_formats: cmd.extend(["-f", f]) cmd.extend(["-o", to, from_]) log.debug("Running python %s", " ".join(cmd)) out = sh.python(*cmd, _err_to_out=True, _cwd=work_dir) log.debug("COMMAND OUTPUT: %s", out) abs_to = os.path.join(work_dir, to) log.info("SHA512SUM: %s SIGNED_FILE: %s", get_hash(abs_to, "sha512"), to) log.info("SHA1SUM: %s SIGNED_FILE: %s", get_hash(abs_to, "sha1"), to) log.debug("Finished signing")