async def build_task_dependencies(chain, task, name, my_task_id): """Recursively build the task dependencies of a task. Args: chain (ChainOfTrust): the chain of trust to add to. task (dict): the task definition to operate on. name (str): the name of the task to operate on. my_task_id (str): the taskId of the task to operate on. Raises: CoTError: on failure. """ log.info("build_task_dependencies {} {}".format(name, my_task_id)) if name.count(':') > 5: raise CoTError("Too deep recursion!\n{}".format(name)) sorted_dependencies = find_sorted_task_dependencies(task, name, my_task_id) for task_name, task_id in sorted_dependencies: if task_id not in chain.dependent_task_ids(): link = LinkOfTrust(chain.context, task_name, task_id) json_path = link.get_artifact_full_path('task.json') try: task_defn = await chain.context.queue.task(task_id) link.task = task_defn chain.links.append(link) # write task json to disk makedirs(os.path.dirname(json_path)) with open(json_path, 'w') as fh: fh.write(format_json(task_defn)) await build_task_dependencies(chain, task_defn, task_name, task_id) except TaskclusterFailure as exc: raise CoTError(str(exc))
def generate_cot(context, path=None): """Format and sign the cot body, and write to disk Args: context (scriptworker.context.Context): the scriptworker context. path (str, optional): The path to write the chain of trust artifact to. If None, this is artifact_dir/public/chainOfTrust.json.asc. Defaults to None. Returns: str: the contents of the chain of trust artifact. Raises: ScriptWorkerException: on schema error. """ body = generate_cot_body(context) try: with open(context.config['cot_schema_path'], "r") as fh: schema = json.load(fh) except (IOError, ValueError) as e: raise ScriptWorkerException("Can't read schema file {}: {}".format( context.config['cot_schema_path'], str(e))) validate_json_schema(body, schema, name="chain of trust") body = format_json(body) path = path or os.path.join(context.config['artifact_dir'], "public", "chainOfTrust.json.asc") if context.config['sign_chain_of_trust']: body = sign(GPG(context), body) with open(path, "w") as fh: print(body, file=fh, end="") return body
def generate_cot(context, parent_path=None): """Format and sign the cot body, and write to disk. Args: context (scriptworker.context.Context): the scriptworker context. parent_path (str, optional): The directory to write the chain of trust artifacts to. If None, this is ``artifact_dir/public/``. Defaults to None. Returns: str: the contents of the chain of trust artifact. Raises: ScriptWorkerException: on schema error. """ body = generate_cot_body(context) schema = load_json_or_yaml( context.config['cot_schema_path'], is_path=True, exception=ScriptWorkerException, message="Can't read schema file {}: %(exc)s".format(context.config['cot_schema_path']) ) validate_json_schema(body, schema, name="chain of trust") body = format_json(body) parent_path = parent_path or os.path.join(context.config['artifact_dir'], 'public') unsigned_path = os.path.join(parent_path, 'chain-of-trust.json') write_to_file(unsigned_path, body) if context.config['sign_chain_of_trust']: ed25519_signature_path = '{}.sig'.format(unsigned_path) ed25519_private_key = ed25519_private_key_from_file(context.config['ed25519_private_key_path']) ed25519_signature = ed25519_private_key.sign(body.encode('utf-8')) write_to_file(ed25519_signature_path, ed25519_signature, file_type='binary') return body
def test_format_json(): expected = "\n".join([ "{", ' "a": 1,', ' "b": [', " 4,", " 3,", " 2", " ],", ' "c": {', ' "d": 5', " }", "}" ]) assert utils.format_json({ "c": { "d": 5 }, "a": 1, "b": [4, 3, 2] }) == expected
def test_format_json(): expected = '\n'.join([ '{', ' "a": 1,', ' "b": [', ' 4,', ' 3,', ' 2', ' ],', ' "c": {', ' "d": 5', ' }', '}' ]) assert utils.format_json({ 'c': { 'd': 5 }, 'a': 1, 'b': [4, 3, 2] }) == expected
def test_format_json(): expected = '\n'.join([ '{', ' "a": 1,', ' "b": [', ' 4,', ' 3,', ' 2', ' ],', ' "c": {', ' "d": 5', ' }', '}' ]) assert utils.format_json({'c': {'d': 5}, 'a': 1, 'b': [4, 3, 2]}) == expected
def verify_cot_signatures(chain): """Verify the signatures of the chain of trust artifacts populated in ``download_cot``. Populate each link.cot with the chain of trust json body. Args: chain (ChainOfTrust): the chain of trust to add to. Raises: CoTError: on failure. """ for link in chain.links: path = link.get_artifact_full_path('public/chainOfTrust.json.asc') gpg_home = os.path.join(chain.context.config['base_gpg_home_dir'], link.worker_impl) gpg = GPG(chain.context, gpg_home=gpg_home) log.debug( "Verifying the {} {} chain of trust signature against {}".format( link.name, link.task_id, gpg_home)) try: with open(path, "r") as fh: contents = fh.read() except OSError as exc: raise CoTError("Can't read {}: {}!".format(path, str(exc))) try: # TODO remove verify_sig pref and kwarg when git repo pubkey # verification works reliably! body = get_body( gpg, contents, verify_sig=chain.context.config['verify_cot_signature']) except ScriptWorkerGPGException as exc: raise CoTError( "GPG Error verifying chain of trust for {}: {}!".format( path, str(exc))) link.cot = load_json( body, exception=CoTError, message="{} {}: Invalid cot json body! %(exc)s".format( link.name, link.task_id)) unsigned_path = link.get_artifact_full_path('chainOfTrust.json') log.debug("Good. Writing json contents to {}".format(unsigned_path)) with open(unsigned_path, "w") as fh: fh.write(format_json(link.cot))
def generate_cot(context, parent_path=None): """Format and sign the cot body, and write to disk. Args: context (scriptworker.context.Context): the scriptworker context. parent_path (str, optional): The directory to write the chain of trust artifacts to. If None, this is ``artifact_dir/public/``. Defaults to None. Returns: str: the contents of the chain of trust artifact. Raises: ScriptWorkerException: on schema error. """ body = generate_cot_body(context) schema = load_json_or_yaml( context.config['cot_schema_path'], is_path=True, exception=ScriptWorkerException, message="Can't read schema file {}: %(exc)s".format( context.config['cot_schema_path'])) validate_json_schema(body, schema, name="chain of trust") body = format_json(body) parent_path = parent_path or os.path.join(context.config['artifact_dir'], 'public') asc_path = os.path.join(parent_path, "chainOfTrust.json.asc") unsigned_path = os.path.join(parent_path, 'chain-of-trust.json') write_to_file(unsigned_path, body) if context.config['sign_chain_of_trust']: ed25519_signature_path = '{}.sig'.format(unsigned_path) ed25519_private_key = ed25519_private_key_from_file( context.config['ed25519_private_key_path']) ed25519_signature = ed25519_private_key.sign(body.encode('utf-8')) write_to_file(ed25519_signature_path, ed25519_signature, file_type='binary') body = sign(GPG(context), body) write_to_file(asc_path, body) return body