Skip to content

Commit

Permalink
Merge pull request #2491 from flatcar/chewi/split-sbsign-job
Browse files Browse the repository at this point in the history
Do Secure Boot signing for official builds in a separate additional job
  • Loading branch information
chewi authored Dec 4, 2024
2 parents c90a73a + e6e3daf commit 0059a33
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 313 deletions.
22 changes: 13 additions & 9 deletions build_image
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ DEFINE_string disk_layout "" \
"The disk layout type to use for this image."
DEFINE_string group "${DEFAULT_GROUP}" \
"The update group."
DEFINE_boolean generate_update "${FLAGS_FALSE}" \
"Generate update payload. (prod only)"
DEFINE_boolean extract_update "${FLAGS_TRUE}" \
"Extract the /usr partition for generating updates."
"Extract the /usr partition for generating updates. Only valid for the prod image."
DEFINE_boolean generate_update "${FLAGS_TRUE}" \
"Generate update payload for testing. The update is signed with a dev key. The kernel is signed with a dev key (unofficial builds) or not at all (official builds). Only valid for the prod image. Implies --extract_update."
DEFINE_string developer_data "" \
"Insert a custom cloudinit file into the image."
DEFINE_string devcontainer_binhost "${DEFAULT_DEVCONTAINER_BINHOST}" \
Expand Down Expand Up @@ -139,6 +139,11 @@ fi
# Create the output directory and temporary mount points.
mkdir -p "${BUILD_DIR}"

# --generate_update implies --extract_update.
if [[ ${FLAGS_generate_update} -eq ${FLAGS_TRUE} ]]; then
FLAGS_extract_update=${FLAGS_TRUE}
fi

DISK_LAYOUT="${FLAGS_disk_layout:-base}"
CONTAINER_LAYOUT="${FLAGS_disk_layout:-container}"

Expand Down Expand Up @@ -169,11 +174,12 @@ fi
if [[ "${PROD_IMAGE}" -eq 1 ]]; then
IMAGE_BUILD_TYPE="prod"
create_prod_image ${FLATCAR_PRODUCTION_IMAGE_NAME} ${DISK_LAYOUT} ${FLAGS_group} ${FLAGS_base_pkg} ${FLAGS_base_sysexts}
if [[ ${FLAGS_generate_update} -eq ${FLAGS_TRUE} ]]; then
generate_update "${FLATCAR_PRODUCTION_IMAGE_NAME}" ${DISK_LAYOUT}
elif [[ ${FLAGS_extract_update} -eq ${FLAGS_TRUE} ]]; then
if [[ ${FLAGS_extract_update} -eq ${FLAGS_TRUE} ]]; then
extract_update "${FLATCAR_PRODUCTION_IMAGE_NAME}" "${DISK_LAYOUT}"
fi
if [[ ${FLAGS_generate_update} -eq ${FLAGS_TRUE} ]]; then
generate_update "${FLATCAR_PRODUCTION_IMAGE_NAME}" "${DISK_LAYOUT}"
fi
if [[ "${PROD_TAR}" -eq 1 ]]; then
create_prod_tar ${FLATCAR_PRODUCTION_IMAGE_NAME}
fi
Expand All @@ -182,9 +188,7 @@ if [[ "${SYSEXT}" -eq 1 ]]; then
create_prod_sysexts "${FLATCAR_PRODUCTION_IMAGE_NAME}"
fi

if [[ ${FLAGS_generate_update} -eq ${FLAGS_TRUE} ]] || \
[[ ${FLAGS_extract_update} -eq ${FLAGS_TRUE} ]]
then
if [[ ${FLAGS_extract_update} -eq ${FLAGS_TRUE} ]]; then
zip_update_tools
fi

Expand Down
126 changes: 89 additions & 37 deletions build_library/build_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,57 +61,43 @@ delete_prompt() {
extract_update() {
local image_name="$1"
local disk_layout="$2"
local update_path="${BUILD_DIR}/${image_name%_image.bin}_update.bin"
local update="${BUILD_DIR}/${image_name%_image.bin}_update.bin"

"${BUILD_LIBRARY_DIR}/disk_util" --disk_layout="${disk_layout}" \
extract "${BUILD_DIR}/${image_name}" "USR-A" "${update_path}"
extract "${BUILD_DIR}/${image_name}" "USR-A" "${update}"

# Compress image
files_to_evaluate+=( "${update_path}" )
files_to_evaluate+=( "${update}" )
compress_disk_images files_to_evaluate

# For production as well as dev builds we generate a dev-key-signed update
# payload for running tests (the signature won't be accepted by production systems).
local update_test="${BUILD_DIR}/flatcar_test_update.gz"
delta_generator \
-private_key "/usr/share/update_engine/update-payload-key.key.pem" \
-new_image "${update_path}" \
-new_kernel "${BUILD_DIR}/${image_name%.bin}.vmlinuz" \
-out_file "${update_test}"
}

zip_update_tools() {
# There isn't a 'dev' variant of this zip, so always call it production.
local update_zip="flatcar_production_update.zip"

info "Generating update tools zip"
# Make sure some vars this script needs are exported
export REPO_MANIFESTS_DIR SCRIPTS_DIR
"${BUILD_LIBRARY_DIR}/generate_au_zip.py" \
--arch "$(get_sdk_arch)" --output-dir "${BUILD_DIR}" --zip-name "${update_zip}"
}

generate_update() {
local image_name="$1"
local disk_layout="$2"
local image_kernel="${BUILD_DIR}/${image_name%.bin}.vmlinuz"
local update_prefix="${image_name%_image.bin}_update"
local update="${BUILD_DIR}/${update_prefix}"
local update="${BUILD_DIR}/${image_name%_image.bin}_update.bin"
local devkey="/usr/share/update_engine/update-payload-key.key.pem"

# Extract the partition if it isn't extracted already.
[[ -s ${update} ]] || extract_update "${image_name}" "${disk_layout}"

echo "Generating update payload, signed with a dev key"
"${BUILD_LIBRARY_DIR}/disk_util" --disk_layout="${disk_layout}" \
extract "${BUILD_DIR}/${image_name}" "USR-A" "${update}.bin"
delta_generator \
-private_key "${devkey}" \
-new_image "${update}.bin" \
-new_image "${update}" \
-new_kernel "${image_kernel}" \
-out_file "${update}.gz"
-out_file "${BUILD_DIR}/flatcar_test_update.gz"
}

# Compress image
declare -a files_to_evaluate
files_to_evaluate+=( "${update}.bin" )
compress_disk_images files_to_evaluate
zip_update_tools() {
# There isn't a 'dev' variant of this zip, so always call it production.
local update_zip="flatcar_production_update.zip"

info "Generating update tools zip"
# Make sure some vars this script needs are exported
local -x REPO_MANIFESTS_DIR SCRIPTS_DIR
"${BUILD_LIBRARY_DIR}/generate_au_zip.py" \
--arch "$(get_sdk_arch)" --output-dir "${BUILD_DIR}" --zip-name "${update_zip}"
}

# ldconfig cannot generate caches for non-native arches.
Expand Down Expand Up @@ -805,10 +791,12 @@ EOF
seek=${verity_offset} count=64 bs=1 status=none
fi

# Sign the kernel after /usr is in a consistent state and verity is calculated
[[ ${COREOS_OFFICIAL:-0} -ne 1 ]] && \
do_sbsign --output "${root_fs_dir}/boot/flatcar/vmlinuz-a"{,}
cleanup_sbsign_certs
# Sign the kernel after /usr is in a consistent state and verity is
# calculated. Only for unofficial builds as official builds get signed later.
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
do_sbsign --output "${root_fs_dir}/boot/flatcar/vmlinuz-a"{,}
cleanup_sbsign_certs
fi

if [[ -n "${image_kernel}" ]]; then
# copying kernel from vfat so ignore the permissions
Expand Down Expand Up @@ -894,3 +882,67 @@ EOF
cleanup_mounts "${root_fs_dir}"
trap - EXIT
}

sbsign_image() {
local image_name="$1"
local disk_layout="$2"
local root_fs_dir="$3"
local image_kernel="$4"
local pcr_policy="$5"
local image_grub="$6"

local disk_img="${BUILD_DIR}/${image_name}"
local EFI_ARCH

case "${BOARD}" in
amd64-usr) EFI_ARCH="x64" ;;
arm64-usr) EFI_ARCH="aa64" ;;
*) die "Unknown board ${BOARD@Q}" ;;
esac

"${BUILD_LIBRARY_DIR}/disk_util" --disk_layout="${disk_layout}" \
mount "${disk_img}" "${root_fs_dir}"
trap "cleanup_mounts '${root_fs_dir}'; cleanup_sbsign_certs" EXIT

# Sign the kernel with the shim-embedded key.
do_sbsign --output "${root_fs_dir}/boot/flatcar/vmlinuz-a"{,}

if [[ -n "${image_kernel}" ]]; then
# copying kernel from vfat so ignore the permissions
cp --no-preserve=mode \
"${root_fs_dir}/boot/flatcar/vmlinuz-a" \
"${BUILD_DIR}/${image_kernel}"
fi

# Sign GRUB and mokmanager(mm) with the shim-embedded key.
do_sbsign --output "${root_fs_dir}/boot/EFI/boot/grub${EFI_ARCH}.efi"{,}
do_sbsign --output "${root_fs_dir}/boot/EFI/boot/mm${EFI_ARCH}.efi"{,}

# copying from vfat so ignore permissions
if [[ -n "${image_grub}" ]]; then
cp --no-preserve=mode "${root_fs_dir}/boot/EFI/boot/grub${EFI_ARCH}.efi" \
"${BUILD_DIR}/${image_grub}"
fi

if [[ -n "${pcr_policy}" ]]; then
mkdir -p "${BUILD_DIR}/pcrs"
"${BUILD_LIBRARY_DIR}"/generate_kernel_hash.py \
"${root_fs_dir}/boot/flatcar/vmlinuz-a" "${FLATCAR_VERSION}" \
>"${BUILD_DIR}/pcrs/kernel.config"
fi

cleanup_mounts "${root_fs_dir}"
cleanup_sbsign_certs
trap - EXIT

if [[ -n "${pcr_policy}" ]]; then
"${BUILD_LIBRARY_DIR}"/generate_grub_hashes.py \
"${disk_img}" /usr/lib/grub/ "${BUILD_DIR}/pcrs" "${FLATCAR_VERSION}"

info "Generating $pcr_policy"
pushd "${BUILD_DIR}" >/dev/null
zip --quiet -r -9 "${BUILD_DIR}/${pcr_policy}" pcrs
popd >/dev/null
rm -rf "${BUILD_DIR}/pcrs"
fi
}
2 changes: 1 addition & 1 deletion build_library/grub_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ case "${FLAGS_target}" in
--output "${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi" \
"${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi"
else
# Official build: Copy the unsigned files.
# Official build: Copy signed shim and mm for signing later.
sudo cp "${BOARD_ROOT}/usr/lib/shim/mm${EFI_ARCH}.efi" \
"${ESP_DIR}/EFI/boot/mm${EFI_ARCH}.efi"
sudo cp "${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi" \
Expand Down
100 changes: 0 additions & 100 deletions build_library/modify_image_util.sh

This file was deleted.

32 changes: 32 additions & 0 deletions build_library/prod_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ EOF
"${image_initrd_contents_wtd}" \
"${image_disk_usage}"

# Official builds will sign and upload these files later, so remove them to
# prevent them from being uploaded now.
if [[ ${COREOS_OFFICIAL:-0} -eq 1 ]]; then
rm -v \
"${BUILD_DIR}/${image_kernel}" \
"${BUILD_DIR}/${image_pcr_policy}" \
"${BUILD_DIR}/${image_grub}"
fi

local files_to_evaluate=( "${BUILD_DIR}/${image_name}" )
compress_disk_images files_to_evaluate
}
Expand Down Expand Up @@ -225,3 +234,26 @@ create_prod_sysexts() {
-out_file "${BUILD_DIR}/flatcar_test_update-${name}.gz"
done
}

sbsign_prod_image() {
local image_name="$1"
local disk_layout="$2"

info "Signing production image ${image_name} for Secure Boot"
local root_fs_dir="${BUILD_DIR}/rootfs"
local image_prefix="${image_name%.bin}"
local image_kernel="${image_prefix}.vmlinuz"
local image_pcr_policy="${image_prefix}_pcr_policy.zip"
local image_grub="${image_prefix}.grub"

sbsign_image \
"${image_name}" \
"${disk_layout}" \
"${root_fs_dir}" \
"${image_kernel}" \
"${image_pcr_policy}" \
"${image_grub}"

local files_to_evaluate=( "${BUILD_DIR}/${image_name}" )
compress_disk_images files_to_evaluate
}
Loading

0 comments on commit 0059a33

Please sign in to comment.