Skip to content

Commit c7859a7

Browse files
committed
Rework sealed build process
Main goal is to reduce signing logic duplication between the systemd-boot and UKI generation. However, this quickly snowballed into wanting to actually verify by providing a custom secure boot keys to bcvk that things worked. This depends on bootc-dev/bcvk#170 Now as part of that, I ran into what I think are bugs in pesign; this cuts things back over to using sbsign. I'll file a tracker for that separately. Finally as part of this, just remove the TMT example that builds a sealed image but doesn't actually verify it works - it's already drifted from what we do outside here. Ultimately what we need is to shift some of this into the Fedora examples and we just fetch it here anyways. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters <[email protected]>
1 parent 7a53236 commit c7859a7

32 files changed

+156
-558
lines changed

Dockerfile

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,26 @@ WORKDIR /src
3838
# First we download all of our Rust dependencies
3939
RUN --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothome cargo fetch
4040

41+
FROM buildroot as sdboot-content
42+
# Writes to /out
43+
RUN /src/contrib/packaging/configure-systemdboot download
44+
45+
# NOTE: Every RUN instruction past this point should use `--network=none`; we want to ensure
46+
# all external dependencies are clearly delineated.
47+
4148
FROM buildroot as build
4249
# Build RPM directly from source, using cached target directory
4350
RUN --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothome --network=none RPM_VERSION=${pkgversion} /src/contrib/packaging/build-rpm
4451

52+
FROM buildroot as sdboot-signed
53+
# The secureboot key and cert are passed via Justfile
54+
# We write the signed binary into /out
55+
RUN --network=none \
56+
--mount=type=bind,from=sdboot-content,target=/run/sdboot-package \
57+
--mount=type=secret,id=secureboot_key \
58+
--mount=type=secret,id=secureboot_cert \
59+
/src/contrib/packaging/configure-systemdboot sign
60+
4561
# This "build" includes our unit tests
4662
FROM build as units
4763
# A place that we're more likely to be able to set xattrs
@@ -57,7 +73,10 @@ RUN --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothom
5773
FROM base
5874
# See the Justfile for possible variants
5975
ARG variant
60-
RUN --mount=type=bind,from=packaging,target=/run/packaging /run/packaging/configure-variant "${variant}"
76+
RUN --network=none --mount=type=bind,from=packaging,target=/run/packaging \
77+
--mount=type=bind,from=sdboot-content,target=/run/sdboot-content \
78+
--mount=type=bind,from=sdboot-signed,target=/run/sdboot-signed \
79+
/run/packaging/configure-variant "${variant}"
6180
# Support overriding the rootfs at build time conveniently
6281
ARG rootfs=
6382
RUN --mount=type=bind,from=packaging,target=/run/packaging /run/packaging/configure-rootfs "${variant}" "${rootfs}"

Dockerfile.cfsuki

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
11
# Override via --build-arg=base=<image> to use a different base
22
ARG base=localhost/bootc
3-
# This is where we get the tools to build the UKI
4-
ARG buildroot=quay.io/centos/centos:stream10
5-
63
FROM $base AS base
74

8-
FROM $buildroot as buildroot-base
9-
RUN <<EORUN
10-
set -xeuo pipefail
11-
12-
# systemd-udev is required for /usr/lib/systemd/systemd-measure which
13-
# is used by ukify as invoked with the `--measure` flag below. Not
14-
# strictly required, but nice to have the measured PCR values in the
15-
# output.
16-
dnf install -y systemd-ukify systemd-udev pesign openssl
17-
dnf clean all
18-
EORUN
19-
20-
FROM buildroot-base as kernel
5+
FROM base as kernel
6+
RUN dnf -y install systemd-ukify epel-release && dnf -y install sbsigntools
217
# Must be passed
228
ARG COMPOSEFS_FSVERITY
23-
RUN --mount=type=secret,id=key \
24-
--mount=type=secret,id=cert \
9+
RUN --network=none \
10+
--mount=type=secret,id=secureboot_key \
11+
--mount=type=secret,id=secureboot_cert \
2512
--mount=type=bind,from=base,target=/target \
2613
<<EOF
2714
set -xeuo pipefail
@@ -31,30 +18,24 @@ RUN --mount=type=secret,id=key \
3118

3219
cmdline="composefs=${COMPOSEFS_FSVERITY} console=ttyS0,115200n8 enforcing=0 rw"
3320

34-
# pesign uses NSS database so create it from input cert/key
35-
mkdir pesign
36-
certutil -N -d pesign --empty-password
37-
openssl pkcs12 -export -password 'pass:' -inkey /run/secrets/key -in /run/secrets/cert -out db.p12
38-
pk12util -i db.p12 -W '' -d pesign
39-
subject=$(openssl x509 -in /run/secrets/cert -subject | grep '^subject=CN=' | sed 's/^subject=CN=//')
40-
21+
# Use sbsign to re-sign the entire UKI with our key
4122
kver=$(cd /target/usr/lib/modules && echo *)
4223
ukify build \
4324
--linux "/target/usr/lib/modules/$kver/vmlinuz" \
4425
--initrd "/target/usr/lib/modules/$kver/initramfs.img" \
4526
--uname="${kver}" \
4627
--cmdline "${cmdline}" \
4728
--os-release "@/target/usr/lib/os-release" \
48-
--signtool pesign \
49-
--secureboot-certificate-dir "pesign" \
50-
--secureboot-certificate-name "${subject}" \
29+
--signtool sbsign \
30+
--secureboot-private-key "/run/secrets/secureboot_key" \
31+
--secureboot-certificate "/run/secrets/secureboot_cert" \
5132
--measure \
5233
--json pretty \
5334
--output "/boot/$kver.efi"
5435
EOF
5536

5637
FROM base as final
57-
RUN --mount=type=bind,from=kernel,target=/run/kernel <<EOF
38+
RUN --network=none --mount=type=bind,from=kernel,target=/run/kernel <<EOF
5839
set -xeuo pipefail
5940
kver=$(cd /usr/lib/modules && echo *)
6041
mkdir -p /boot/EFI/Linux

Dockerfile.sdboot

Lines changed: 0 additions & 50 deletions
This file was deleted.

Justfile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@ testimage_label := "bootc.testimage=1"
3535
# ```
3636
# TODO: Gather more info and file a buildah bug
3737
base_buildargs := ""
38-
buildargs := "--build-arg=base=" + base + " --build-arg=variant=" + variant
38+
buildargs := "--build-arg=base=" + base + " --build-arg=variant=" + variant + " --secret=id=secureboot_key,src=target/test-secureboot/db.key --secret=id=secureboot_cert,src=target/test-secureboot/db.crt"
39+
# Args for build-sealed (no base arg, it sets that itself)
40+
sealed_buildargs := "--build-arg=variant=" + variant + " --secret=id=secureboot_key,src=target/test-secureboot/db.key --secret=id=secureboot_cert,src=target/test-secureboot/db.crt"
3941

40-
# Build the container image from current sources.
42+
# The default target: build the container image from current sources.
4143
# Note commonly you might want to override the base image via e.g.
4244
# `just build --build-arg=base=quay.io/fedora/fedora-bootc:42`
43-
build:
45+
build: _keygen
4446
podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} .
45-
./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}} {{buildroot_base}}
47+
./hack/build-sealed {{variant}} {{base_img}}-bin {{base_img}} {{sealed_buildargs}}
48+
49+
# Generate Secure Boot keys (only for our own CI/testing)
50+
_keygen:
51+
./hack/generate-secureboot-keys
4652

4753
# Build a sealed image from current sources.
4854
build-sealed:
@@ -75,7 +81,7 @@ package: _packagecontainer
7581
# This container image has additional testing content and utilities
7682
build-integration-test-image: build
7783
cd hack && podman build {{base_buildargs}} -t {{integration_img}}-bin -f Containerfile .
78-
./tests/build-sealed {{variant}} {{integration_img}}-bin {{integration_img}} {{buildroot_base}}
84+
./hack/build-sealed {{variant}} {{integration_img}}-bin {{integration_img}} {{sealed_buildargs}}
7985
# Keep these in sync with what's used in hack/lbi
8086
podman pull -q --retry 5 --retry-delay 5s quay.io/curl/curl:latest quay.io/curl/curl-base:latest registry.access.redhat.com/ubi9/podman:latest
8187

@@ -119,7 +125,7 @@ test-tmt *ARGS: build-integration-test-image _build-upgrade-image
119125
# Generate a local synthetic upgrade
120126
_build-upgrade-image:
121127
cat tmt/tests/Dockerfile.upgrade | podman build -t {{integration_upgrade_img}}-bin --from={{integration_img}}-bin -
122-
./tests/build-sealed {{variant}} {{integration_upgrade_img}}-bin {{integration_upgrade_img}} {{buildroot_base}}
128+
./hack/build-sealed {{variant}} {{integration_upgrade_img}}-bin {{integration_upgrade_img}} {{sealed_buildargs}}
123129

124130
# Assume the localhost/bootc-integration image is up to date, and just run tests.
125131
# Useful for iterating on tests quickly.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
# Helper for signing and re-injecting systemd-boot
3+
set -euo pipefail
4+
op=$1
5+
shift
6+
7+
sdboot="usr/lib/systemd/boot/efi/systemd-bootx64.efi"
8+
sdboot_bn=$(basename ${sdboot})
9+
10+
case $op in
11+
download)
12+
mkdir -p /out
13+
cd /out
14+
dnf -y download systemd-boot-unsigned
15+
;;
16+
sign)
17+
mkdir -p /out
18+
rpm -Uvh /run/sdboot-package/out/*.rpm
19+
# Sign with sbsign using db certificate and key
20+
sbsign \
21+
--key /run/secrets/secureboot_key \
22+
--cert /run/secrets/secureboot_cert \
23+
--output /out/${sdboot_bn} \
24+
/${sdboot}
25+
ls -al /out/${sdboot_bn}
26+
;;
27+
*) echo "Unknown operation $op" 1>&2; exit 1
28+
;;
29+
esac

contrib/packaging/configure-variant

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Configure system for a specific bootc variant
33
set -xeuo pipefail
44

5+
dn=$(dirname $0)
6+
57
VARIANT="${1:-}"
68

79
if [ -z "$VARIANT" ]; then
@@ -12,8 +14,14 @@ fi
1214
# Handle variant-specific configuration
1315
case "${VARIANT}" in
1416
*-sdboot)
15-
# Install systemd-boot and remove bootupd
16-
dnf -y install systemd-boot-unsigned
17+
# Install systemd-boot and remove bootupd;
18+
# We downloaded this in an earlier phase
19+
sdboot="usr/lib/systemd/boot/efi/systemd-bootx64.efi"
20+
sdboot_bn=$(basename ${sdboot})
21+
rpm -Uvh /run/sdboot-content/out/*.rpm
22+
# And override with our signed binary
23+
install -m 0644 /run/sdboot-signed/out/${sdboot_bn} /${sdboot}
24+
1725
# Uninstall bootupd
1826
rpm -e bootupd
1927
rm -rf /usr/lib/bootupd/updates

contrib/packaging/fedora-extra.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ git-core
77
jq
88
# We now always build a package in the container build
99
rpm-build
10+
# Used for signing
11+
sbsigntools
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# This file defines the package name for systemd-boot
2+
systemd-boot-unsigned

contrib/packaging/install-buildroot

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ set -xeuo pipefail
44
cd $(dirname $0)
55
. /usr/lib/os-release
66
case $ID in
7-
centos|rhel) dnf config-manager --set-enabled crb;;
7+
centos|rhel)
8+
dnf config-manager --set-enabled crb
9+
# Enable EPEL for sbsigntools
10+
dnf -y install epel-release
11+
;;
812
fedora) dnf -y install dnf-utils 'dnf5-command(builddep)';;
913
esac
1014
# Handle version skew, xref https://gitlab.com/redhat/centos-stream/containers/bootc/-/issues/1174

contrib/packaging/install-rpm-and-setup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ env DRACUT_NO_XATTR=1 dracut --add bootc -vf /usr/lib/modules/$kver/initramfs.im
2222
touch /usr/lib/.bootc-dev-stamp
2323

2424
# Workaround for https://github.com/bootc-dev/bootc/issues/1546
25-
rm -rf /root/buildinfo
25+
rm -rf /root/buildinfo /var/roothome/buildinfo

0 commit comments

Comments
 (0)