def get_mar_verification_key(cert_type, fmt, keyid): """Get the public key file for the format/cert_type. Args: cert_type (str): the cert scope string fmt (str): the signing format keyid (str): the key id to use (can be None) Raises: SigningScriptError: if no key is found Returns: str: the public key to use with ``-k`` """ # Cert types are like ... cert_type = cert_type.split(":")[-1] data_dir = os.path.join(os.path.dirname(__file__), "data") try: if keyid is None: return os.path.join(data_dir, _DEFAULT_MAR_VERIFY_KEYS[fmt][cert_type]) else: # Make sure you can't try and read outside of the data directory if "/" in keyid: raise SigningScriptError("/ not allowed in keyids") keyid = os.path.basename(keyid) return os.path.join(data_dir, f"{keyid}.pem") except KeyError as err: raise SigningScriptError(f"Can't find mar verify key for {fmt}, {cert_type} ({keyid}):\n{err}")
async def sign_file_with_autograph(context, from_, fmt, to=None): """Signs a file with autograph and writes the result to arg `to` or `from_` if `to` is None. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with to (str, optional): the target path to sign to. If None, overwrite `from_`. Defaults to None. Raises: Requests.RequestException: on failure Returns: str: the path to the signed file """ if not utils.is_autograph_signing_format(fmt): raise SigningScriptError( "No signing servers found supporting signing format {}".format( fmt)) cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt]) if not servers: raise SigningScriptError( "No signing servers found with cert type {}".format(cert_type)) s = servers[0] to = to or from_ with open(from_, 'rb') as fin: input_bytes = fin.read() # build and run the signature request sign_req = [{"input": base64.b64encode(input_bytes)}] log.debug("using the default autograph keyid for %s", s.user) url = "%s/sign/file" % s.server async def make_sign_req(): auth = HawkAuth(id=s.user, key=s.password) with requests.Session() as session: r = session.post(url, json=sign_req, auth=auth) log.debug("Autograph response: {}".format( r.text[:120] if len(r.text) >= 120 else r.text)) r.raise_for_status() return r.json() sign_resp = await retry_async(make_sign_req) with open(to, 'wb') as fout: fout.write(base64.b64decode(sign_resp[0]['signed_file'])) log.info("autograph wrote signed_file %s to %s", from_, to) return to
async def sign_gpg_with_autograph(context, from_, fmt): """Signs file with autograph and writes the results to a file. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: list: the path to the signed file, and sig. """ if not utils.is_autograph_signing_format(fmt): raise SigningScriptError(f"Not an autograph format: {fmt}") cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) s = servers[0] to = f"{from_}.asc" input_bytes = open(from_, 'rb').read() signature = await sign_with_autograph(s, input_bytes, fmt, 'data') with open(to, 'w') as fout: fout.write(signature) return [from_, to]
def _get_tarfile_compression(compression): compression = compression.lstrip('.') if compression not in ('bz2', 'gz'): raise SigningScriptError( "{} not a supported tarfile compression format!".format(compression) ) return compression
async def sign_mar384_with_autograph_hash(context, from_, fmt, to=None): """Signs a hash with autograph, injects it into the file, and writes the result to arg `to` or `from_` if `to` is None. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with to (str, optional): the target path to sign to. If None, overwrite `from_`. Defaults to None. Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: str: the path to the signed file """ cert_type = task.task_cert_type(context) # Get any key id that the task may have specified fmt, keyid = utils.split_autograph_format(fmt) # Call to check that we have a server available get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) hash_algo, expected_signature_length = 'sha384', 512 # Add a dummy signature into a temporary file (TODO: dedup with mardor.cli do_hash) with tempfile.TemporaryFile() as tmp: with open(from_, 'rb') as f: add_signature_block(f, tmp, hash_algo) tmp.seek(0) with MarReader(tmp) as m: hashes = m.calculate_hashes() h = hashes[0][1] signature = await sign_hash_with_autograph(context, h, fmt, keyid) # Add a signature to the MAR file (TODO: dedup with mardor.cli do_add_signature) if len(signature) != expected_signature_length: raise SigningScriptError( "signed mar hash signature has invalid length for hash algo {}. Got {} expected {}.".format(hash_algo, len(signature), expected_signature_length) ) # use the tmp file in case param `to` is `from_` which causes stream errors tmp_dst = tempfile.NamedTemporaryFile(mode='w+b', delete=False) with open(tmp_dst.name, 'w+b') as dst: with open(from_, 'rb') as src: add_signature_block(src, dst, hash_algo, signature) to = to or from_ shutil.copyfile(tmp_dst.name, to) os.unlink(tmp_dst.name) verify_mar_signature(cert_type, fmt, to, keyid) log.info("wrote mar with autograph signed hash %s to %s", from_, to) return to
async def sign_hash_with_autograph(context, hash_, fmt, keyid=None): """Signs hash with autograph and returns the result. Args: context (Context): the signing context hash_ (bytes): the input hash to sign fmt (str): the format to sign with keyid (str): which key to use on autograph (optional) Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: bytes: the signature """ if not utils.is_autograph_signing_format(fmt): raise SigningScriptError(f"Not an autograph format: {fmt}") cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) s = servers[0] signature = base64.b64decode(await sign_with_autograph(s, hash_, fmt, 'hash', keyid)) return signature
def get_autograph_config(autograph_configs, cert_type, signing_formats, raise_on_empty=False): """Get the autograph config for given `signing_formats` and `cert_type`. Args: autograph_configs (dict of lists of lists): the contents of `autograph_configs`. cert_type (str): the certificate type - essentially signing level, separating release vs nightly vs dep. signing_formats (list): the signing formats the server needs to support raise_on_empty (bool): flag to raise errors. Optional. Defaults to False. Raises: SigningScriptError: when no suitable signing server is found Returns: An Autograph object """ for a in autograph_configs.get(cert_type, []): if a and (set(a.formats) & set(signing_formats)): return a if raise_on_empty: raise SigningScriptError(f"No autograph config found with cert type {cert_type} and formats {signing_formats}") return None
async def sign_xpi(context, orig_path, fmt): """Sign language packs with autograph. This validates both the file extension and the language pack ID is sane. Args: context (Context): the signing context orig_path (str): the source file to sign fmt (str): the format to sign with Returns: str: the path to the signed xpi """ file_base, file_extension = os.path.splitext(orig_path) if file_extension not in (".xpi", ".zip"): raise SigningScriptError("Expected a .xpi") ext_id = _extension_id(orig_path, fmt) log.info("Identified {} as extension id: {}".format(orig_path, id)) kwargs = {"extension_id": ext_id} # Sign the appropriate inner files await sign_file_with_autograph(context, orig_path, fmt, **kwargs) return orig_path
async def sign_omnija(context, orig_path, fmt): """Call the appropriate helper function to do omnija signing. Args: context (Context): the signing context orig_path (str): the source file to sign fmt (str): the format to sign with Raises: SigningScriptError: on unknown suffix. Returns: str: the path to the signed archive """ file_base, file_extension = os.path.splitext(orig_path) # Convert dmg to tarball if file_extension == ".dmg": await _convert_dmg_to_tar_gz(context, orig_path) orig_path = "{}.tar.gz".format(file_base) ext_to_fn = {".zip": sign_omnija_zip, ".tar.bz2": sign_omnija_tar, ".tar.gz": sign_omnija_tar} for ext, signing_func in ext_to_fn.items(): if orig_path.endswith(ext): return await signing_func(context, orig_path, fmt) raise SigningScriptError("Unknown omnija file format for {}".format(orig_path))
def get_suitable_signing_servers(signing_servers, cert_type, signing_formats, raise_on_empty_list=False): """Get the list of signing servers for given `signing_formats` and `cert_type`. Args: signing_servers (dict of lists of lists): the contents of `signing_server_config`. cert_type (str): the certificate type - essentially signing level, separating release vs nightly vs dep. signing_formats (list): the signing formats the server needs to support raise_on_empty_list (bool): flag to raise errors. Optional. Defaults to False. Raises: FailedSubprocess: on subprocess error while signing. SigningScriptError: when no suitable signing server is found Returns: list of lists: the list of signing servers. """ if cert_type not in signing_servers: suitable_signing_servers = [] else: suitable_signing_servers = [s for s in signing_servers[cert_type] if set(signing_formats) & set(s.formats)] if raise_on_empty_list and not suitable_signing_servers: raise SigningScriptError( f"No signing servers found with cert type {cert_type} and formats {signing_formats}" ) else: return suitable_signing_servers
async def sign_file_with_autograph(context, from_, fmt, to=None): """Signs file with autograph and writes the results to a file. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with to (str, optional): the target path to sign to. If None, overwrite `from_`. Defaults to None. Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: str: the path to the signed file """ if not utils.is_autograph_signing_format(fmt): raise SigningScriptError(f"Not an autograph format: {fmt}") cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) s = servers[0] to = to or from_ input_bytes = open(from_, 'rb').read() signed_bytes = base64.b64decode(await sign_with_autograph(s, input_bytes, fmt, 'file')) with open(to, 'wb') as fout: fout.write(signed_bytes) return to
def _extension_id(filename, fmt): """Return a list of id's for the langpacks. Side effect of additionally verifying langpack manifests. """ xpi = zipfile.ZipFile(filename, "r") manifest = {} for manifest_name in ("manifest.json", "webextension/manifest.json"): try: with xpi.open(manifest_name, "r") as f: manifest = json.load(f) break except KeyError: log.debug("{} doesn't exist in {}...".format(manifest_name, filename)) if not manifest.get("applications", {}).get("gecko", {}).get("id"): raise SigningScriptError("{} is not a valid xpi".format(filename)) if "langpack" in fmt and not ( "languages" in manifest and "langpack_id" in manifest and LANGPACK_RE.match(manifest["applications"]["gecko"]["id"]) and filename.endswith(".xpi") ): raise SigningScriptError("{} is not a valid langpack".format(filename)) return manifest["applications"]["gecko"]["id"]
async def _create_zipfile(context, to, files, tmp_dir=None, mode="w"): work_dir = context.config["work_dir"] tmp_dir = tmp_dir or os.path.join(work_dir, "unzipped") try: log.info("Creating zipfile {}...".format(to)) with zipfile.ZipFile(to, mode=mode, compression=zipfile.ZIP_DEFLATED) as z: for f in files: relpath = os.path.relpath(f, tmp_dir) z.write(f, arcname=relpath) return to except Exception as e: raise SigningScriptError(e)
async def _create_tarfile(context, to, files, compression, tmp_dir=None): work_dir = context.config["work_dir"] tmp_dir = tmp_dir or os.path.join(work_dir, "untarred") compression = _get_tarfile_compression(compression) try: log.info("Creating tarfile {}...".format(to)) with tarfile.open(to, mode="w:{}".format(compression)) as t: for f in files: relpath = os.path.relpath(f, tmp_dir) t.add(f, arcname=relpath, filter=_owner_filter) return to except Exception as e: raise SigningScriptError(e)
async def _extract_tarfile(context, from_, compression, tmp_dir=None): work_dir = context.config["work_dir"] tmp_dir = tmp_dir or os.path.join(work_dir, "untarred") compression = _get_tarfile_compression(compression) try: files = [] rm(tmp_dir) utils.mkdir(tmp_dir) with tarfile.open(from_, mode="r:{}".format(compression)) as t: t.extractall(path=tmp_dir) for name in t.getnames(): path = os.path.join(tmp_dir, name) os.path.isfile(path) and files.append(path) return files except Exception as e: raise SigningScriptError(e)
async def _extract_zipfile(context, from_, files=None, tmp_dir=None): work_dir = context.config["work_dir"] tmp_dir = tmp_dir or os.path.join(work_dir, "unzipped") log.debug("Extracting {} from {} to {}...".format(files or "all files", from_, tmp_dir)) try: extracted_files = [] rm(tmp_dir) utils.mkdir(tmp_dir) with zipfile.ZipFile(from_, mode="r") as z: if files is not None: for name in files: z.extract(name, path=tmp_dir) extracted_files.append(os.path.join(tmp_dir, name)) else: for name in z.namelist(): extracted_files.append(os.path.join(tmp_dir, name)) z.extractall(path=tmp_dir) return extracted_files except Exception as e: raise SigningScriptError(e)
async def sign_authenticode_zip(context, orig_path, fmt, *, authenticode_comment=None, **kwargs): """Sign a zipfile with authenticode, using autograph as a backend. Extract the zip and only sign unsigned files that don't match certain patterns (see `_should_sign_windows`). Then recreate the zip. Args: context (Context): the signing context orig_path (str): the source file to sign fmt (str): the format to sign with comment (str): The authenticode comment to sign with, if present. currently only used for msi files. (Defaults to None) Returns: str: the path to the signed zip """ file_base, file_extension = os.path.splitext(orig_path) # This will get cleaned up when we nuke `work_dir`. Clean up at that point # rather than immediately after `sign_signcode`, to optimize task runtime # speed over disk space. tmp_dir = None # Extract the zipfile if file_extension == ".zip": tmp_dir = tempfile.mkdtemp(prefix="zip", dir=context.config["work_dir"]) files = await _extract_zipfile(context, orig_path, tmp_dir=tmp_dir) else: files = [orig_path] files_to_sign = [file for file in files if _should_sign_windows(file)] if not files_to_sign: raise SigningScriptError("Did not find any files to sign, all files: {}".format(files)) # Sign the appropriate inner files tasks = [sign_authenticode_file(context, file_, fmt, authenticode_comment=authenticode_comment) for file_ in files_to_sign] done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) [f.result() for f in done] if file_extension == ".zip": # Recreate the zipfile await _create_zipfile(context, orig_path, files, tmp_dir=tmp_dir) return orig_path
def verify_mar_signature(cert_type, fmt, mar): """Verify a mar signature, via mardor. Args: cert_type (str): the cert scope string fmt (str): the signing format mar (str): the path to the mar file Raises: SigningScriptError: if the signature doesn't verify, or the nick isn't found """ mar_verify_nick = get_mar_verification_nick(cert_type, fmt) try: mar_path = os.path.join(os.path.dirname(sys.executable), 'mar') cmd = [mar_path, '-k', mar_verify_nick, '-v', mar] log.info("Running %s", cmd) subprocess.check_call(cmd, stdout=sys.stdout, stderr=sys.stderr) log.info("Verified signature.") except subprocess.CalledProcessError as e: raise SigningScriptError(e)
def get_mar_verification_nick(cert_type, fmt): """Get the mardor nick for the format/cert_type. Args: cert_type (str): the cert scope string fmt (str): the signing format Raises: SigningScriptError: if no nick is found Returns: str: the mardor nick to use with ``-k`` """ cert_type = cert_type.split(':')[-1] try: return ':mozilla-{}'.format(_MAR_VERIFY_FORMATS[fmt][cert_type]) except KeyError as err: raise SigningScriptError( "Can't find mar verify format for {}, {}:\n{}".format( fmt, cert_type, err))
async def sign_with_autograph(server, input_bytes, fmt, autograph_method, keyid=None, extension_id=None): """Signs data with autograph and returns the result. Args: server (SigningServer): the server to connect to sign input_bytes (bytes): the source data to sign fmt (str): the format to sign with autograph_method (str): which autograph method to use to sign. must be one of 'file', 'hash', or 'data' keyid (str): which key to use on autograph (optional) extension_id (str): which id to send to autograph for the extension (optional) Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: bytes: the signed data """ if autograph_method not in {'file', 'hash', 'data'}: raise SigningScriptError(f"Unsupported autograph method: {autograph_method}") sign_req = make_signing_req(input_bytes, server, fmt, keyid, extension_id) log.debug("signing data with format %s with %s", fmt, autograph_method) url = f"{server.server}/sign/{autograph_method}" sign_resp = await retry_async(call_autograph, args=(url, server.user, server.password, sign_req), attempts=3, sleeptime_kwargs={'delay_factor': 2.0}) if autograph_method == 'file': return sign_resp[0]['signed_file'] else: return sign_resp[0]['signature']
def verify_mar_signature(cert_type, fmt, mar, keyid=None): """Verify a mar signature, via mardor. Args: cert_type (str): the cert scope string fmt (str): the signing format mar (str): the path to the mar file keyid (str, optional): the key id to use (can be None) Raises: SigningScriptError: if the signature doesn't verify, or the nick isn't found """ mar_verify_key = get_mar_verification_key(cert_type, fmt, keyid) try: mar_path = os.path.join(os.path.dirname(sys.executable), "mar") cmd = [mar_path, "-k", mar_verify_key, "-v", mar] log.info("Running %s", cmd) subprocess.check_call(cmd, stdout=sys.stdout, stderr=sys.stderr) log.info("Verified signature.") except subprocess.CalledProcessError as e: raise SigningScriptError(e)
def _langpack_id(filename): """Return a list of id's for the langpacks. Side Affect of checking if filenames are actually langpacks. """ langpack = zipfile.ZipFile(filename, 'r') id = None with langpack.open('manifest.json', 'r') as f: manifest = json.load(f) if not ('languages' in manifest and 'langpack_id' in manifest and 'applications' in manifest and 'gecko' in manifest['applications'] and 'id' in manifest['applications']['gecko'] and LANGPACK_RE.match( manifest['applications']['gecko']['id'] )): raise SigningScriptError( '{} is not a valid langpack'.format(filename) ) id = manifest['applications']['gecko']['id'] return id
async def sign_signcode(context, orig_path, fmt): """Sign a zipfile with authenticode. Extract the zip and only sign unsigned files that don't match certain patterns (see `_should_sign_windows`). Then recreate the zip. Args: context (Context): the signing context orig_path (str): the source file to sign fmt (str): the format to sign with Returns: str: the path to the signed zip """ file_base, file_extension = os.path.splitext(orig_path) # This will get cleaned up when we nuke `work_dir`. Clean up at that point # rather than immediately after `sign_signcode`, to optimize task runtime # speed over disk space. tmp_dir = None # Extract the zipfile if file_extension == '.zip': tmp_dir = tempfile.mkdtemp(prefix="zip", dir=context.config['work_dir']) files = await _extract_zipfile(context, orig_path, tmp_dir=tmp_dir) else: files = [orig_path] files_to_sign = [file for file in files if _should_sign_windows(file)] if not files_to_sign: raise SigningScriptError( "Did not find any files to sign, all files: {}".format(files)) # Sign the appropriate inner files for from_ in files_to_sign: await sign_file(context, from_, fmt) if file_extension == '.zip': # Recreate the zipfile await _create_zipfile(context, orig_path, files, tmp_dir=tmp_dir) return orig_path
async def sign_with_autograph(session, server, input_file, fmt, autograph_method, keyid=None, extension_id=None): """Signs data with autograph and returns the result. Args: session (aiohttp.ClientSession): client session object server (Autograph): the server to connect to sign input_file (file object): the source data to sign fmt (str): the format to sign with autograph_method (str): which autograph method to use to sign. must be one of 'file', 'hash', or 'data' keyid (str): which key to use on autograph (optional) extension_id (str): which id to send to autograph for the extension (optional) Raises: aiohttp.ClientError: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: bytes: the signed data """ if autograph_method not in {"file", "hash", "data"}: raise SigningScriptError(f"Unsupported autograph method: {autograph_method}") keyid = keyid or server.key_id sign_req = make_signing_req(input_file, fmt, keyid, extension_id) url = f"{server.url}/sign/{autograph_method}" sign_resp = await retry_async( call_autograph, args=(session, url, server.client_id, server.access_key, sign_req), attempts=3, sleeptime_kwargs={"delay_factor": 2.0} ) if autograph_method == "file": return sign_resp[0]["signed_file"] else: return sign_resp[0]["signature"]
def _get_tarfile_compression(compression): compression = compression.lstrip(".") if compression not in ("bz2", "gz"): raise SigningScriptError("{} not a supported tarfile compression format!".format(compression)) return compression
async def sign_file_with_autograph(context, from_, fmt, to=None): """Signs a file with autograph and writes the result to arg `to` or `from_` if `to` is None. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with to (str, optional): the target path to sign to. If None, overwrite `from_`. Defaults to None. Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: str: the path to the signed file """ if not utils.is_autograph_signing_format(fmt): raise SigningScriptError( "No signing servers found supporting signing format {}".format( fmt)) cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) s = servers[0] to = to or from_ with open(from_, 'rb') as fin: input_bytes = fin.read() # We need to base64 data for autograph. b64encode() returns bytes, though. We need utf8 strings # to make Python's JSON decoder happy base64_input = base64.b64encode(input_bytes).decode('utf-8') # build and run the signature request sign_req = [{"input": base64_input}] if utils.is_apk_autograph_signing_format(fmt): # We don't want APKs to have their compression changed sign_req[0]['options'] = {'zip': 'passthrough'} if utils.is_sha1_apk_autograph_signing_format(fmt): # We ask for a SHA1 digest from Autograph # https://github.com/mozilla-services/autograph/pull/166/files sign_req[0]['options']['pkcs7_digest'] = "SHA1" log.debug("using the default autograph keyid for %s", s.user) url = "%s/sign/file" % s.server async def make_sign_req(): auth = HawkAuth(id=s.user, key=s.password) with requests.Session() as session: r = session.post(url, json=sign_req, auth=auth) log.debug("Autograph response: {}".format( r.text[:120] if len(r.text) >= 120 else r.text)) r.raise_for_status() return r.json() sign_resp = await retry_async(make_sign_req) with open(to, 'wb') as fout: fout.write(base64.b64decode(sign_resp[0]['signed_file'])) log.info("autograph wrote signed_file %s to %s", from_, to) return to
async def sign_mar384_with_autograph_hash(context, from_, fmt, to=None): """Signs a hash with autograph, injects it into the file, and writes the result to arg `to` or `from_` if `to` is None. Args: context (Context): the signing context from_ (str): the source file to sign fmt (str): the format to sign with to (str, optional): the target path to sign to. If None, overwrite `from_`. Defaults to None. Raises: Requests.RequestException: on failure SigningScriptError: when no suitable signing server is found for fmt Returns: str: the path to the signed file """ log.info( "sign_mar384_with_autograph_hash(): signing {} with {}... using autograph /sign/hash" .format(from_, fmt)) if not utils.is_autograph_signing_format(fmt): raise SigningScriptError( "No signing servers found supporting signing format {}".format( fmt)) cert_type = task.task_cert_type(context) servers = get_suitable_signing_servers(context.signing_servers, cert_type, [fmt], raise_on_empty_list=True) s = servers[0] to = to or from_ hash_algo, expected_signature_length = 'sha384', 512 # Add a dummy signature into a temporary file (TODO: dedup with mardor.cli do_hash) tmp = tempfile.TemporaryFile() with open(from_, 'rb') as f: add_signature_block(f, tmp, hash_algo) tmp.seek(0) with MarReader(tmp) as m: hashes = m.calculate_hashes() h = hashes[0][1] tmp.close() # build and run the hash signature request sign_req = [{"input": base64.b64encode(h).decode('ascii')}] log.debug( "signing mar with hash alg %s using the default autograph keyid for %s", hash_algo, s.user) url = "%s/sign/hash" % s.server async def make_sign_req(): auth = HawkAuth(id=s.user, key=s.password) with requests.Session() as session: r = session.post(url, json=sign_req, auth=auth) log.debug("Autograph response: {}".format( r.text[:120] if len(r.text) >= 120 else r.text)) r.raise_for_status() return r.json() sign_resp = await retry_async(make_sign_req) signature = base64.b64decode(sign_resp[0]['signature']) # Add a signature to the MAR file (TODO: dedup with mardor.cli do_add_signature) if len(signature) != expected_signature_length: raise SigningScriptError( "signed mar hash signature has invalid length for hash algo {}. Got {} expected {}." .format(hash_algo, len(signature), expected_signature_length)) # use the tmp file in case param `to` is `from_` which causes stream errors tmp_dst = tempfile.NamedTemporaryFile(mode='w+b', delete=False) with open(tmp_dst.name, 'w+b') as dst: with open(from_, 'rb') as src: add_signature_block(src, dst, hash_algo, signature) shutil.copyfile(tmp_dst.name, to) os.unlink(tmp_dst.name) verify_mar_signature(cert_type, fmt, to) log.info("wrote mar with autograph signed hash %s to %s", from_, to) return to
def die(*args, **kwargs): raise SigningScriptError("dying!")
def context_die(*args, **kwargs): raise SigningScriptError("dying")