Refactor SB signing code and sign official builds with Azure Key Vault

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
This commit is contained in:
James Le Cuirot 2024-11-01 12:40:43 +00:00
parent 0eb1d4a287
commit d8a8704f92
No known key found for this signature in database
GPG Key ID: 1226415D00DD3137
3 changed files with 110 additions and 80 deletions

View File

@ -20,6 +20,7 @@ BUILD_DIR="${FLAGS_output_root}/${BOARD}/${IMAGE_SUBDIR}"
OUTSIDE_OUTPUT_DIR="../build/images/${BOARD}/${IMAGE_SUBDIR}" OUTSIDE_OUTPUT_DIR="../build/images/${BOARD}/${IMAGE_SUBDIR}"
source "${BUILD_LIBRARY_DIR}/reports_util.sh" || exit 1 source "${BUILD_LIBRARY_DIR}/reports_util.sh" || exit 1
source "${BUILD_LIBRARY_DIR}/sbsign_util.sh" || exit 1
set_build_symlinks() { set_build_symlinks() {
local build=$(basename ${BUILD_DIR}) local build=$(basename ${BUILD_DIR})
@ -826,13 +827,8 @@ EOF
fi fi
# Sign the kernel after /usr is in a consistent state and verity is calculated # Sign the kernel after /usr is in a consistent state and verity is calculated
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then do_sbsign --output "${root_fs_dir}/boot/flatcar/vmlinuz-a"{,}
sudo sbsign --key /usr/share/sb_keys/shim.key \ cleanup_sbsign_certs
--cert /usr/share/sb_keys/shim.pem \
"${root_fs_dir}/boot/flatcar/vmlinuz-a"
sudo mv "${root_fs_dir}/boot/flatcar/vmlinuz-a.signed" \
"${root_fs_dir}/boot/flatcar/vmlinuz-a"
fi
if [[ -n "${image_kernel}" ]]; then if [[ -n "${image_kernel}" ]]; then
# copying kernel from vfat so ignore the permissions # copying kernel from vfat so ignore the permissions

View File

@ -35,6 +35,7 @@ switch_to_strict_mode
# must be sourced after flags are parsed. # must be sourced after flags are parsed.
. "${BUILD_LIBRARY_DIR}/toolchain_util.sh" || exit 1 . "${BUILD_LIBRARY_DIR}/toolchain_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1 . "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/sbsign_util.sh" || exit 1
# Our GRUB lives under flatcar/grub so new pygrub versions cannot find grub.cfg # Our GRUB lives under flatcar/grub so new pygrub versions cannot find grub.cfg
GRUB_DIR="flatcar/grub/${FLAGS_target}" GRUB_DIR="flatcar/grub/${FLAGS_target}"
@ -42,29 +43,30 @@ GRUB_DIR="flatcar/grub/${FLAGS_target}"
# Modules required to boot a standard CoreOS configuration # Modules required to boot a standard CoreOS configuration
CORE_MODULES=( normal search test fat part_gpt search_fs_uuid gzio search_part_label terminal gptprio configfile memdisk tar echo read btrfs ) CORE_MODULES=( normal search test fat part_gpt search_fs_uuid gzio search_part_label terminal gptprio configfile memdisk tar echo read btrfs )
# Name of the core image, depends on target
CORE_NAME=
SBAT_ARG=() SBAT_ARG=()
case "${FLAGS_target}" in case "${FLAGS_target}" in
i386-pc)
CORE_MODULES+=( biosdisk serial )
CORE_NAME="core.img"
;;
x86_64-efi) x86_64-efi)
CORE_MODULES+=( serial linux efi_gop efinet pgp http tftp tpm ) EFI_ARCH="x64"
CORE_NAME="core.efi"
SBAT_ARG=( --sbat "${BOARD_ROOT}/usr/share/grub/sbat.csv" )
;;
x86_64-xen)
CORE_NAME="core.elf"
;; ;;
arm64-efi) arm64-efi)
EFI_ARCH="aa64"
;;
esac
case "${FLAGS_target}" in
x86_64-efi|arm64-efi)
GRUB_IMAGE="EFI/boot/grub${EFI_ARCH}.efi"
CORE_MODULES+=( serial linux efi_gop efinet pgp http tftp tpm ) CORE_MODULES+=( serial linux efi_gop efinet pgp http tftp tpm )
CORE_NAME="core.efi"
SBAT_ARG=( --sbat "${BOARD_ROOT}/usr/share/grub/sbat.csv" ) SBAT_ARG=( --sbat "${BOARD_ROOT}/usr/share/grub/sbat.csv" )
;; ;;
i386-pc)
GRUB_IMAGE="${GRUB_DIR}/core.img"
CORE_MODULES+=( biosdisk serial )
;;
x86_64-xen)
GRUB_IMAGE="xen/pvboot-x86_64.elf"
;;
*) *)
die_notrace "Unknown GRUB target ${FLAGS_target}" die_notrace "Unknown GRUB target ${FLAGS_target}"
;; ;;
@ -88,6 +90,7 @@ ESP_DIR=
LOOP_DEV= LOOP_DEV=
cleanup() { cleanup() {
cleanup_sbsign_certs
if [[ -d "${ESP_DIR}" ]]; then if [[ -d "${ESP_DIR}" ]]; then
if mountpoint -q "${ESP_DIR}"; then if mountpoint -q "${ESP_DIR}"; then
sudo umount "${ESP_DIR}" sudo umount "${ESP_DIR}"
@ -121,7 +124,7 @@ done
if [[ -z ${MOUNTED} ]]; then if [[ -z ${MOUNTED} ]]; then
failboat "${LOOP_DEV}p1 where art thou? udev has forsaken us!" failboat "${LOOP_DEV}p1 where art thou? udev has forsaken us!"
fi fi
sudo mkdir -p "${ESP_DIR}/${GRUB_DIR}" sudo mkdir -p "${ESP_DIR}/${GRUB_DIR}" "${ESP_DIR}/${GRUB_IMAGE%/*}"
info "Compressing modules in ${GRUB_DIR}" info "Compressing modules in ${GRUB_DIR}"
for file in "${GRUB_SRC}"/*{.lst,.mod}; do for file in "${GRUB_SRC}"/*{.lst,.mod}; do
@ -163,7 +166,7 @@ if [[ ! -f "${ESP_DIR}/flatcar/grub/grub.cfg.tar" ]]; then
-C "${GRUB_TEMP_DIR}" "grub.cfg" -C "${GRUB_TEMP_DIR}" "grub.cfg"
fi fi
info "Generating ${GRUB_DIR}/${CORE_NAME}" info "Generating ${GRUB_IMAGE}"
sudo grub-mkimage \ sudo grub-mkimage \
--compression=auto \ --compression=auto \
--format "${FLAGS_target}" \ --format "${FLAGS_target}" \
@ -171,7 +174,7 @@ sudo grub-mkimage \
--config "${ESP_DIR}/${GRUB_DIR}/load.cfg" \ --config "${ESP_DIR}/${GRUB_DIR}/load.cfg" \
--memdisk "${ESP_DIR}/flatcar/grub/grub.cfg.tar" \ --memdisk "${ESP_DIR}/flatcar/grub/grub.cfg.tar" \
"${SBAT_ARG[@]}" \ "${SBAT_ARG[@]}" \
--output "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \ --output "${ESP_DIR}/${GRUB_IMAGE}" \
"${CORE_MODULES[@]}" "${CORE_MODULES[@]}"
for mod in "${CORE_MODULES[@]}"; do for mod in "${CORE_MODULES[@]}"; do
@ -180,6 +183,37 @@ done
# Now target specific steps to make the system bootable # Now target specific steps to make the system bootable
case "${FLAGS_target}" in case "${FLAGS_target}" in
x86_64-efi|arm64-efi)
info "Installing default ${FLAGS_target} UEFI bootloader."
# Sign GRUB and mokmanager(mm) with the shim-embedded key.
do_sbsign --output "${ESP_DIR}/${GRUB_IMAGE}"{,}
do_sbsign --output "${ESP_DIR}/EFI/boot/mm${EFI_ARCH}.efi" \
"${BOARD_ROOT}/usr/lib/shim/mm${EFI_ARCH}.efi"
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
# Unofficial build: Sign shim with our development key.
sudo sbsign \
--key /usr/share/sb_keys/DB.key \
--cert /usr/share/sb_keys/DB.crt \
--output "${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi" \
"${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi"
else
# Official build: Copy our pre-signed shim.
sudo cp "${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi.signed" \
"${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi"
fi
# copying from vfat so ignore permissions
if [[ -n ${FLAGS_copy_efi_grub} ]]; then
cp --no-preserve=mode "${ESP_DIR}/${GRUB_IMAGE}" \
"${FLAGS_copy_efi_grub}"
fi
if [[ -n ${FLAGS_copy_shim} ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi" \
"${FLAGS_copy_shim}"
fi
;;
i386-pc) i386-pc)
info "Installing MBR and the BIOS Boot partition." info "Installing MBR and the BIOS Boot partition."
sudo cp "${GRUB_SRC}/boot.img" "${ESP_DIR}/${GRUB_DIR}" sudo cp "${GRUB_SRC}/boot.img" "${ESP_DIR}/${GRUB_DIR}"
@ -190,67 +224,12 @@ case "${FLAGS_target}" in
sudo dd bs=448 count=1 status=none if="${LOOP_DEV}" \ sudo dd bs=448 count=1 status=none if="${LOOP_DEV}" \
of="${ESP_DIR}/${GRUB_DIR}/mbr.bin" of="${ESP_DIR}/${GRUB_DIR}/mbr.bin"
;; ;;
x86_64-efi)
info "Installing default x86_64 UEFI bootloader."
sudo mkdir -p "${ESP_DIR}/EFI/boot"
# Use the test keys for signing unofficial builds
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
# Sign the GRUB with the shim-embedded key
sudo sbsign --key /usr/share/sb_keys/shim.key \
--cert /usr/share/sb_keys/shim.pem \
"${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}"
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}.signed" \
"${ESP_DIR}/EFI/boot/grubx64.efi"
sudo rm "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}"
# Sign the mokmanager(mm) with the shim-embedded key
sudo sbsign --key /usr/share/sb_keys/shim.key \
--cert /usr/share/sb_keys/shim.pem \
"/usr/lib/shim/mmx64.efi"
sudo cp "/usr/lib/shim/mmx64.efi.signed" \
"${ESP_DIR}/EFI/boot/mmx64.efi"
sudo sbsign --key /usr/share/sb_keys/DB.key \
--cert /usr/share/sb_keys/DB.crt \
--output "${ESP_DIR}/EFI/boot/bootx64.efi" \
"/usr/lib/shim/shim.efi"
else
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/EFI/boot/grubx64.efi"
sudo cp "/usr/lib/shim/shim.efi" \
"${ESP_DIR}/EFI/boot/bootx64.efi"
sudo cp "/usr/lib/shim/mmx64.efi" \
"${ESP_DIR}/EFI/boot/mmx64.efi"
fi
# copying from vfat so ignore permissions
if [[ -n "${FLAGS_copy_efi_grub}" ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/grubx64.efi" \
"${FLAGS_copy_efi_grub}"
fi
if [[ -n "${FLAGS_copy_shim}" ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/bootx64.efi" \
"${FLAGS_copy_shim}"
fi
;;
x86_64-xen) x86_64-xen)
info "Installing default x86_64 Xen bootloader." info "Installing default x86_64 Xen bootloader."
sudo mkdir -p "${ESP_DIR}/xen" "${ESP_DIR}/boot/grub" sudo mkdir -p "${ESP_DIR}/boot/grub"
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/xen/pvboot-x86_64.elf"
sudo cp "${BUILD_LIBRARY_DIR}/menu.lst" \ sudo cp "${BUILD_LIBRARY_DIR}/menu.lst" \
"${ESP_DIR}/boot/grub/menu.lst" "${ESP_DIR}/boot/grub/menu.lst"
;; ;;
arm64-efi)
info "Installing default arm64 UEFI bootloader."
sudo mkdir -p "${ESP_DIR}/EFI/boot"
#FIXME(andrejro): shim not ported to aarch64
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/EFI/boot/bootaa64.efi"
if [[ -n "${FLAGS_copy_efi_grub}" ]]; then
# copying from vfat so ignore permissions
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/bootaa64.efi" \
"${FLAGS_copy_efi_grub}"
fi
;;
esac esac
cleanup cleanup

View File

@ -0,0 +1,55 @@
# Copyright (c) 2024 The Flatcar Maintainers.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
SBSIGN_KEY="/usr/share/sb_keys/shim.key"
SBSIGN_CERT="/usr/share/sb_keys/shim.pem"
else
SBSIGN_KEY="pkcs11:token=flatcar-dev-cert"
unset SBSIGN_CERT
fi
PKCS11_MODULE_PATH="/usr/$(get_sdk_libdir)/pkcs11/azure_kms_pkcs11.so"
PKCS11_ENV=(
AZURE_KEYVAULT_URL="https://chewi-test.vault.azure.net/"
PKCS11_MODULE_PATH="${PKCS11_MODULE_PATH}"
AWS_KMS_PKCS11_DEBUG=1
)
get_sbsign_cert() {
if [[ ${SBSIGN_KEY} != pkcs11:* || -s ${SBSIGN_CERT-} ]]; then
return
fi
SBSIGN_CERT=$(mktemp -t signing-cert.XXXXXXXXXX.pem)
info "Fetching ${SBSIGN_KEY} from Azure"
# Needs Key Vault Reader role.
env "${PKCS11_ENV[@]}" p11-kit export-object \
--provider "${PKCS11_MODULE_PATH}" \
"${SBSIGN_KEY};type=cert" \
| tee "${SBSIGN_CERT}"
}
cleanup_sbsign_certs() {
if [[ ${SBSIGN_CERT-} == "${TMPDIR-/tmp}"/* ]]; then
rm -f -- "${SBSIGN_CERT}"
fi
}
do_sbsign() {
get_sbsign_cert
info "Signing ${@:$#} with ${SBSIGN_KEY}"
if [[ ${SBSIGN_KEY} == pkcs11:* ]]; then
set -- --engine pkcs11 "${@}"
fi
# Needs Key Vault Crypto User role.
sudo env "${PKCS11_ENV[@]}" sbsign \
--key "${SBSIGN_KEY}" \
--cert "${SBSIGN_CERT}" \
"${@}"
}