Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UKI #2

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d4ff867
Drop sudo usage to run as root in GitHub workflows
travier Jul 30, 2024
ecb92b3
Bump ESP & boot partitions size
travier Jul 30, 2024
4926cdd
github: Remove Dependabot config
travier Jul 30, 2024
357ed4c
WIP
travier Jul 30, 2024
aa95e61
cmd-build: Enable composeFS signing
jbtrystram May 29, 2024
ebec947
WIP composefs
travier Jul 30, 2024
f15cbb1
wip
travier Jul 30, 2024
b18e70b
wip
travier Jul 30, 2024
e2e6bb0
w
travier Jul 30, 2024
51f7073
wip
travier Jul 30, 2024
948e842
w
travier Jul 30, 2024
70329f7
w
travier Jul 30, 2024
4958459
w
travier Jul 30, 2024
6b01d29
w
travier Jul 31, 2024
0c19f6c
re-generate composefs metadata
travier Jul 31, 2024
24fc075
wip
travier Jul 31, 2024
1a037ab
wip uki name
travier Jul 31, 2024
339ad75
w
travier Jul 31, 2024
22a752a
w
travier Aug 1, 2024
5d1fb41
w
travier Aug 1, 2024
209f342
w
travier Aug 1, 2024
d2daacf
enable composeFS integrity on ostree repo config
jbtrystram Aug 26, 2024
681afbd
Merge branch 'coreos:main' into main-uki
jbtrystram Aug 29, 2024
e410446
print executed commands
jbtrystram Aug 29, 2024
4dc7fba
include composefs in commit metadata
jbtrystram Sep 2, 2024
a4956bc
create_disk.sh is no longer used, it's now osbuild.
jbtrystram Sep 2, 2024
7fe56b6
wip
jbtrystram Sep 2, 2024
5abc874
Revert "include composefs in commit metadata"
jbtrystram Sep 2, 2024
dcd1c25
cmd-build: add a config file for ostree-prepare-root
jbtrystram Sep 4, 2024
0d37e96
cmd-build print out the composeFS digest
jbtrystram Sep 4, 2024
81448fd
cmd-build add missing --repo to ostree
jbtrystram Sep 4, 2024
5d43942
cmd-build : fix missing quote
jbtrystram Sep 4, 2024
0955f90
Revert "cmd-build: add a config file for ostree-prepare-root"
jbtrystram Sep 5, 2024
1998c87
cmd-build: fix os-release argument
jbtrystram Sep 10, 2024
900cae7
secureboot: sign systemd-boot efi binary
jbtrystram Sep 10, 2024
8a59d24
--amend
jbtrystram Sep 10, 2024
3cab964
Get systemd-boot from the ostree commit
travier Sep 14, 2024
cc3782a
temporarily build 2 UKIs
travier Sep 14, 2024
eac72c9
extract efistub from commit
travier Sep 14, 2024
8ae1f76
Copy systemd-boot-unsigned content to host
travier Sep 14, 2024
dc114a3
fix missing escape on sbsign call
jbtrystram Sep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .github/dependabot.yml

This file was deleted.

112 changes: 109 additions & 3 deletions src/cmd-build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
set -euxo pipefail

dn=$(dirname "$0")
# shellcheck source=src/cmdlib.sh
Expand Down Expand Up @@ -38,6 +38,8 @@ Usage: coreos-assembler build --help
--autolock=VERSION If no base lockfile used, create one from any arch build of `VERSION`.
Note this is automatically enabled when adding to an existing multi-arch
non-strict build.
--sign-composefs Sign the composeFS metadata and attach the signature to the OSTree commit.
This will also insert the public key into the rootfs for signature verification.

Additional environment variables supported:

Expand All @@ -62,8 +64,9 @@ TAG=
STRICT=
CONFIG_ARCHIVE=1
AUTOLOCK_VERSION=
SIGN_COMPOSEFS=
rc=0
options=$(getopt --options hfFt: --longoptions tag:,help,fetch,force,version:,parent:,parent-build:,delay-meta-merge,force-nocache,force-image,skip-prune,prepare-only,strict,skip-config-archive,autolock:,versionary -- "$@") || rc=$?
options=$(getopt --options hfFt: --longoptions tag:,help,fetch,force,version:,parent:,parent-build:,delay-meta-merge,force-nocache,force-image,skip-prune,prepare-only,strict,skip-config-archive,autolock:,versionary,sign-composefs -- "$@") || rc=$?
[ $rc -eq 0 ] || {
print_help
exit 1
Expand Down Expand Up @@ -123,6 +126,9 @@ while true; do
shift
TAG=$1
;;
--sign-composefs)
SIGN_COMPOSEFS=true
;;
--)
shift
break
Expand Down Expand Up @@ -257,6 +263,13 @@ if [ -n "${PARENT_BUILD}" ]; then
fi
fi

# TODO
SIGN_COMPOSEFS=true
# If composeFS signing is enabled, generate the signature key
if test -n "${SIGN_COMPOSEFS}"; then
gen_ed25519_signing_key
fi

# Calculate image input checksum now and gather previous image build variables if any
ks_path="${configdir}"/image.ks
if [ -f "${ks_path}" ]; then
Expand Down Expand Up @@ -354,12 +367,14 @@ fi
if [ ! -f "${workdir}"/builds/builds.json ] && [ ! -f "${fetch_stamp}" ] ; then
fatal "Must fetch before building"
fi

composefs="$(jq -r .composefs < "${image_json}")"
case "${composefs}" in
false)
;;
true)
true | signed)
ostree config --repo="${tmprepo}" set ex-integrity.composefs "true"
ostree config --repo="${tmprepo}" set ex-fsverity.required 'true'
;;
*) fatal "Unhandled composefs setting: ${composefs}" ;;
esac
Expand All @@ -375,6 +390,84 @@ RUNVM_NONET=1 runcompose_tree --cache-only ${FORCE} \
"${extra_compose_args[@]}"
strip_out_lockfile_digests "$lockfile_out".tmp
/usr/lib/coreos-assembler/finalize-artifact "${lockfile_out}"{.tmp,}

commit=$(jq -r '.["ostree-commit"]' < "${composejson}")

ostree sign \
--repo "${tmprepo}" \
--sign-type ed25519 \
--keys-file "${workdir}/tmp/ostree_signing_key.ed25519" \
"$commit"

ostree show --repo "${tmprepo}" "${commit}"
cfs_sig=$(ostree show --repo "${tmprepo}" "$commit" --print-metadata-key=ostree.composefs.digest.v0)
cfs_sig=$(echo "$cfs_sig"| sed 's/\[byte //g; s/\]//g; s/,//g; s/0x//g' | tr -d ' ')
echo "composeFS digest: $cfs_sig"

kernpath="$(ostree ls --repo "${tmprepo}" "${commit}" /usr/lib/modules | sort -h | tail -1 | awk '{print $5}')"
kernver="$(basename "${kernpath}")"
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/modules/${kernver}/vmlinuz" > vmlinuz
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/modules/${kernver}/initramfs.img" > initramfs
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/os-release" > os-release
mkdir -p "/usr/lib/systemd/boot/efi/"
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/addonx64.efi.stub" > /usr/lib/systemd/boot/efi/addonx64.efi.stub
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" > linuxx64.efi.stub
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" > /usr/lib/systemd/boot/efi/systemd-bootx64.efi
ukify build \
--linux "vmlinuz" \
--initrd "initramfs" \
--cmdline "rw mitigations=auto,nosmt ignition.platform.id=qemu console=tty0 console=ttyS0,115200n8 ostree=/ostree/boot.0/fedora-coreos/$(cat vmlinuz initramfs | sha256sum | awk '{print $1}')/0" \
--os-release "@os-release" \
--uname "$kernver" \
--signtool sbsign \
--secureboot-private-key "${workdir}/db.key" \
--secureboot-certificate "${workdir}/db.pem" \
--output "${workdir}/tmp/uki" \
--measure
ukify build \
--linux "vmlinuz" \
--initrd "initramfs" \
--cmdline "rw mitigations=auto,nosmt ignition.platform.id=qemu console=tty0 console=ttyS0,115200n8 ostree=/ostree/boot.1/fedora-coreos/$(cat vmlinuz initramfs | sha256sum | awk '{print $1}')/0" \
--os-release "@os-release" \
--uname "$kernver" \
--signtool sbsign \
--secureboot-private-key "${workdir}/db.key" \
--secureboot-certificate "${workdir}/db.pem" \
--output "${workdir}/tmp/uki.1" \
--measure

# Sign systemd-boot binary
ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" > systemd-bootx64.efi
sbsign \
--key "${workdir}/db.key" \
--cert "${workdir}/db.pem" \
--output "${workdir}/tmp/systemd-bootx64-signed.efi" \
"/usr/lib/systemd/boot/efi/systemd-bootx64.efi"

# mkdir -p "ukirootfs/usr/lib/modules/$kernver/"
# mv uki "ukirootfs/usr/lib/modules/$kernver/uki"
# chown 0:0 "ukirootfs/usr/lib/modules/$kernver/uki"
# chmod 644 "ukirootfs/usr/lib/modules/$kernver/uki"

# ostree_keys=()
# for key in $(ostree show --repo "${tmprepo}" "$commit" --list-metadata-keys); do
# ostree_keys+=("--keep-metadata=$key")
# done

# commit="$(ostree commit \
# --repo "${tmprepo}" \
# --base "$commit" \
# --parent "$commit" \
# --branch "fedora/x86_64/coreos/$(basename "$(ls "${tmprepo}/refs/heads/fedora/x86_64/coreos/"*)")" \
# --subject "$commit + UKI" \
# --sign-type ed25519 \
# --sign-from-file="${workdir}/tmp/ostree_signing_key.ed25519" \
# --generate-composefs-metadata \
# --bootable \
# "${ostree_keys[@]}" \
# ukirootfs)"
# rm -rf ukirootfs

# Very special handling for --write-composejson-to as rpm-ostree doesn't
# write it if the commit didn't change.
if [ -f "${changed_stamp}" ] && [ -f "${composejson}" ]; then
Expand Down Expand Up @@ -448,6 +541,17 @@ echo "New build ID: ${buildid}"
# Also write out a ref with the build ID
ostree --repo="${tmprepo}" refs --create "${buildid}" "${commit}"

# Not sure if we need to add --generate-composefs-metadata as I couldn't find
# any references in ostree man pages.
# is is default since https://github.com/coreos/rpm-ostree/pull/4495/commits/dbe78217c0205dad372c84b2cf0a299003787952 ?

# TODO
# If composefs signing is enabled, sign the last commit
# if test -n "${SIGN_COMPOSEFS}"; then
# ostree sign --keys-file ${TMPDIR}/cosa_key.ed25519 ${commit} --repo=${tmprepo}
# fi
# TODO

"${dn}"/write-commit-object "${tmprepo}" "${commit}" "$(pwd)"

build_timestamp=$(date -u +$RFC3339)
Expand Down Expand Up @@ -514,6 +618,8 @@ else
--label="coreos-assembler.image-input-checksum=${image_input_checksum}" \
--label="org.opencontainers.image.source=${gitsrc}" \
--label="org.opencontainers.image.revision=${config_gitrev}" \
--label="ostree.commit=${commit}" \
--label="ostree.commit.composefs.digest=${cfs_sig}" \
--copymeta-opt=fedora-coreos.stream \
"${last_build_manifest[@]}" \
"${labels[@]}" \
Expand Down
2 changes: 1 addition & 1 deletion src/cmd-buildextend-metal
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ rootfs_size_mb="$(jq '."estimate-mb".final' "$PWD/tmp/ostree-size.json")"
# the size set in the configs since some of them have minimum sizes that
# the platforms require and we want a "default" disk size that has some
# free space.
nonroot_partition_sizes=513
nonroot_partition_sizes=2048
# On s390x there is one more build - Secure Execution case, which has
# different image layout. We add the sizes of the se and verity
# partitions so that they don't "eat into" the 35% buffer (though note
Expand Down
4 changes: 2 additions & 2 deletions src/cmd-fetch
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ dn=$(dirname "$0")
FILE=cache/pkgcache-repo
if [ -d "${FILE}" ]
then
pkgcachesize=$(sudo du --bytes --max-depth 0 "${FILE}" \
pkgcachesize=$( du --bytes --max-depth 0 "${FILE}" \
| awk '{print $1; exit}')
pkglimit=$((1024 * 1024 * 1024 * 5))
if [[ "${pkgcachesize}" -gt "${pkglimit}" ]]
then
sudo cosa prune --pkgcache
cosa prune --pkgcache
fi
fi

Expand Down
2 changes: 1 addition & 1 deletion src/cmd-init
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ source=$1; shift
preflight

if has_privileges; then
sudo chown "$USER:" .
chown "$USER:" .
elif [ ! -w . ]; then
fatal "init: running unprivileged, and current directory not writable"
fi
Expand Down
2 changes: 1 addition & 1 deletion src/cmd-prune
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ if args.pkgcache:
n = len("cache/pkgcache-repo/refs/heads/")
if pkg[n:] not in build_pkg:
print(f"Deleted {pkg[n:]}")
subprocess.call(f"sudo ostree refs --repo=cache/pkgcache-repo --delete {pkg[n:]}", shell=True)
subprocess.call(f" ostree refs --repo=cache/pkgcache-repo --delete {pkg[n:]}", shell=True)

sys.exit(0)

Expand Down
40 changes: 31 additions & 9 deletions src/cmdlib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ has_privileges() {
elif ! capsh --print | grep -q 'Bounding.*cap_sys_admin'; then
info "Missing CAP_SYS_ADMIN; using virt"
COSA_PRIVILEGED=0
elif [ "$(id -u)" != "0" ] && ! sudo true; then
info "Missing sudo privs; using virt"
elif [ "$(id -u)" != "0" ] && ! true; then
info "Missing privs; using virt"
COSA_PRIVILEGED=0
else
COSA_PRIVILEGED=1
Expand Down Expand Up @@ -113,9 +113,9 @@ preflight_kvm() {
if ! has_privileges; then
fatal "running unprivileged, and /dev/kvm not writable"
else
sudo rm -f /dev/kvm
sudo mknod /dev/kvm c 10 232
sudo setfacl -m u:"$USER":rw /dev/kvm
rm -f /dev/kvm
mknod /dev/kvm c 10 232
setfacl -m u:"$USER":rw /dev/kvm
fi
fi
fi
Expand Down Expand Up @@ -563,8 +563,8 @@ runcompose_tree() {
set - "$@" --repo "${repo}" --write-composejson-to "${composejson}"
# we hardcode a umask of 0022 here to make sure that composes are run
# with a consistent value, regardless of the environment
(umask 0022 && sudo -E "$@")
sudo chown -R -h "${USER}":"${USER}" "${tmprepo}"
(umask 0022 && "$@")
chown -R -h "${USER}":"${USER}" "${tmprepo}"
else
runvm_with_cache -- "$@" --repo "${repo}" --write-composejson-to "${composejson}"
fi
Expand All @@ -587,8 +587,8 @@ runcompose_extensions() {
if has_privileges; then
# we hardcode a umask of 0022 here to make sure that composes are run
# with a consistent value, regardless of the environment
(umask 0022 && sudo -E "$@")
sudo chown -R -h "${USER}":"${USER}" "${outputdir}"
(umask 0022 && "$@")
chown -R -h "${USER}":"${USER}" "${outputdir}"
else
# Use a snapshot version of the cache qcow2 to allow multiple users
# of the cache at the same time. This is needed because the extensions
Expand Down Expand Up @@ -1108,3 +1108,25 @@ extract_osrelease_name() {
# shellcheck disable=SC1091,SC2153
(. "$out/os-release" && echo "${NAME}")
}


gen_ed25519_signing_key() {
local key_file="ostree_signing_key"

# Generate the key
openssl genpkey -algorithm ed25519 -outform PEM -out "${TMPDIR}/${key_file}"

# Extract the pubkey
local -r pubkey="$(openssl pkey -outform DER -pubout -in "${TMPDIR}/${key_file}" | tail -c 32 | base64)"

# Write the pubkey in overrides
mkdir -p "${workdir}/overrides/rootfs/etc/ostree/"
echo "$pubkey" > "${workdir}/overrides/rootfs/etc/ostree/initramfs-root-binding.key"

# Convert the private key to base64 for ostree signing
## Extract the seed
local -r seed="$(openssl pkey -outform DER -in "${TMPDIR}/${key_file}" | tail -c 32 | base64)"

## Secret key is the concatenation of seed and public
echo "${seed}${pubkey}" | base64 -d | base64 -w 0 > "${TMPDIR}/${key_file}.ed25519"
}
4 changes: 2 additions & 2 deletions src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ mpp-vars:
bios_boot_size_mb: 1
ppc_prep_size_mb: 4
reserved_part_size_mb: 1
efi_system_size_mb: 127
boot_size_mb: 384
efi_system_size_mb: 512
boot_size_mb: 512
sector_size: 512
four_k_sector_size: 4096
# Filesystem UUID and label definitions. These UUIDs
Expand Down