From 5095c91e9f886c5a1a873e3c31c5af5084752c87 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 11 Jul 2023 10:26:36 +0200 Subject: [PATCH] org.osbuild.ostree.sign: Support `ostree sign` to sign commits This form of signatures has been (build-time-optionally) supported since ostree 2020.4 as an alternative to the old gpg signatures. With the current work on composefs[1] they are becomming more important, as they will allow verification of the commit (and thus the composefs image) during boot, giving us a full trusted boot chain all the way into the ostree userspace. Note: `ostree sign` used to require libsodium and was thus disabled in e.g. the Fedora build of ostree. However, recently[2] it is also supported with openssl, which will let it be more widely used. [1] https://github.com/ostreedev/ostree/pull/2921 [2] https://github.com/ostreedev/ostree/pull/2922 --- stages/org.osbuild.ostree.sign | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 stages/org.osbuild.ostree.sign diff --git a/stages/org.osbuild.ostree.sign b/stages/org.osbuild.ostree.sign new file mode 100755 index 0000000000..95114bda5e --- /dev/null +++ b/stages/org.osbuild.ostree.sign @@ -0,0 +1,69 @@ +#!/usr/bin/python3 +"""Sign a commit in an ostree repo + +Given an ostree commit (referenced by a ref) in a repo and an ed25519 +secret key this adds a signature to the commit detached metadata. +This commit can then be used to validate the commit, during ostree +pull, during boot, or at any other time. + +""" + +import os +import subprocess +import sys +import base64 + +from osbuild import api + +SCHEMA_2 = """ +"options": { + "additionalProperties": false, + "required": ["repo", "ref", "key"], + "properties": { + "repo": { + "description": "Location of the OSTree repo.", + "type": "string" + }, + "ref": { + "description": "OStree ref to create for the commit", + "type": "string", + "default": "" + }, + "key": { + "description": "Path to the secret key", + "type": "string" + } + } +} +""" + + +def ostree(*args, _input=None, **kwargs): + args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] + # Don't print this commandline, as it contains the key as an argument + subprocess.run(["ostree"] + args, + encoding="utf8", + stdout=sys.stderr, + input=_input, + check=True) + + +def main(tree, options): + repo = os.path.join(tree, options["repo"].lstrip("/")) + ref = options["ref"] + keyfile = os.path.join(tree, options["key"].lstrip("/")) + + f = open(keyfile, "rb") + key = f.read() + keyid = base64.b64encode(key).decode("utf8") + + ostree("sign", f"--repo={repo}", ref, keyid) + + +if __name__ == '__main__': + stage_args = api.arguments() + + r = main(stage_args["tree"], + stage_args["options"]) + + sys.exit(r)