Instead of verifying the gpg signature when pull from the actual remote source into the local cache, verify the commit when it is being pulled from the local cache into the output directory. This ensures that the signatures are checked against the provided keys even when the commit was already in the cache and at that time the key might have been different. NB: ostree expects the signature to be present on the remote at the *target* repository, i.e. in our case the output repository. The keys are therefore attached to a temporary remote that is created at the output repository with the same name/id that is used for the actual remote.
84 lines
2.3 KiB
Python
Executable file
84 lines
2.3 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import uuid
|
|
|
|
|
|
def ostree(*args, _input=None, **kwargs):
|
|
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
|
|
print(f"ostree " + " ".join(args), file=sys.stderr)
|
|
subprocess.run(["ostree"] + args,
|
|
encoding="utf-8",
|
|
stdout=sys.stderr,
|
|
input=_input,
|
|
check=True)
|
|
|
|
|
|
def main(options, checksums, cache, output):
|
|
commits = options["commits"]
|
|
|
|
os.makedirs(output, exist_ok=True)
|
|
os.makedirs(cache, exist_ok=True)
|
|
|
|
# Prepare the cache and the output repo
|
|
repo_cache = os.path.join(cache, "repo")
|
|
ostree("init", mode="archive", repo=repo_cache)
|
|
|
|
repo_out = os.path.join(output, "repo")
|
|
ostree("init", mode="archive", repo=repo_out)
|
|
|
|
for commit in checksums:
|
|
remote = commits[commit]["remote"]
|
|
url = remote["url"]
|
|
gpg = remote.get("gpgkeys", [])
|
|
uid = str(uuid.uuid4())
|
|
|
|
ostree("remote", "add",
|
|
"--no-gpg-verify",
|
|
uid, url,
|
|
repo=repo_cache)
|
|
|
|
# this temporary remote is needed to verify
|
|
# the commit signatures via gpg below
|
|
ostree("remote", "add",
|
|
uid, repo_cache,
|
|
repo=repo_out)
|
|
|
|
for key in gpg:
|
|
ostree("remote", "gpg-import", "--stdin", uid,
|
|
repo=repo_out, _input=key)
|
|
|
|
# Transfer the commit: remote → cache
|
|
print(f"pulling {commit}", file=sys.stderr)
|
|
ostree("pull", uid, commit, repo=repo_cache)
|
|
|
|
# Transfer the commit: cache → output
|
|
verify_args = []
|
|
if gpg:
|
|
verify_args = ["--gpg-verify", "--remote", uid]
|
|
|
|
ostree("pull-local", repo_cache, commit,
|
|
*verify_args,
|
|
repo=repo_out)
|
|
|
|
# Remove the temporary remotes again
|
|
ostree("remote", "delete", uid,
|
|
repo=repo_cache)
|
|
|
|
ostree("remote", "delete", uid,
|
|
repo=repo_out)
|
|
|
|
json.dump({}, sys.stdout)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
source_args = json.load(sys.stdin)
|
|
r = main(source_args["options"],
|
|
source_args["checksums"],
|
|
source_args["cache"],
|
|
source_args["output"])
|
|
sys.exit(r)
|