systemd / mkosi

💽 Build Bespoke OS Images
https://mkosi.systemd.io/
1.2k stars 325 forks source link

Support offline signing #1759

Open bluca opened 1 year ago

bluca commented 1 year ago

Currently signing (secureboot, verity) is done inline, ie: mkosi expects access to the private key material during the build. This doesn't work in many setups where the private key is kept on a detached system, accessible only through infrastructure-specific interfaces. The standard pattern there is to do the first build pass, get a list of hashes to sign, ship them off via some method, and get back detached signatures, and do a second build pass to apply such signatures. This is how OBS works for example: https://en.opensuse.org/openSUSE:Build_Service_Signer

So we'd need to support a build mode that creates the partitions and EFI images, but doesn't actually store signatures, and a second mode that takes a stubbed image and detached signatures, and applies them.

MariusSchiffer commented 5 months ago

I started working on this, my approach would be the following:

Question is: Do we defer creating the ESP until we have the signed UKI, or do we use mcopy to replace it?

Am I missing something?

My PR for ukify is here: https://github.com/systemd/systemd/pull/33246

MariusSchiffer commented 5 months ago

For my own reasons, I would like to add an additional file to the output partitions at the same time or before signing. Problem here is that adding this file needs to be done in a reduced cap environment (i.e. no unshare).
I think my best bet here is letting mkosi output a tarball, executing repart and adding roothash myself. Any other ideas for using this signing workflow?

DaanDeMeyer commented 5 months ago

I've thought a little about this, and I think that in this setup the signed UKI should come from a distribution package. Of course this means that the roothash can't be part of the cmdline anymore, which means that https://github.com/systemd/systemd/issues/24027 will need to be solved first so that the roothash can be moved out of the kernel command line. Then the signed UKI and bootloader can be built ahead of time and installed as regular packages.

mkosi can then learn to communicate the roothash to the user, which can then be signed offlline, and then we'll add a VeritySignature setting which can be configured to the offline signed verity signature, after which the build is run again, but this time, we also create the verity signature partition.

Note that this idea also depends on reproducible builds so that you can build once without VeritySignature= and once again later with VeritySignature= without having the roothash change. Alternatively, since we'll have to add an option to systemd-repart anyway to allow specifying the verity signature, users can just call systemd-repart themselves after signing the roothash to insert the verity signature partition into the image, so that stuff doesn't need to be reproducible.

MariusSchiffer commented 5 months ago

Decoupling roothash from the cmdline definitely sounds elegant, so that the UKI does not have to be resigned for partition changes.
In this case, how can the verity signature be verified, and against which key? Builtin kernel keyring or platform keys?

I think in that case (for versioned image-based systems) the cmdline could specify data+verity+sig root partitions by label (instead of roothash), as long as https://github.com/systemd/systemd/issues/24027 is not fully implemented.
I like it.

Only thing which is missing atm is the ability to specify the sig partition on the cmdline