From ed769282caec5711378013214a209d67029872f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Sun, 10 May 2026 19:05:04 +0200 Subject: [PATCH] build: add CoCo addon image build and remove CoCo deps from confidential image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add install_image_coco_addon() to kata-deploy-binaries.sh which: - Unpacks the CoCo guest components and pause image tarballs into a temporary rootfs directory (under the repo root so Docker-in-Docker volume mounts resolve correctly) - Calls image_builder.sh with USE_DOCKER=1, FS_TYPE=erofs, MEASURED_ROOTFS=yes, SKIP_DAX_HEADER=yes, and SKIP_ROOTFS_CHECK=yes to produce kata-containers-coco-addon.img + root_hash_coco-addon.txt Add the rootfs-image-coco-addon-tarball Makefile target with dependencies on pause-image-tarball and coco-guest-components-tarball. Remove pause-image-tarball and coco-guest-components-tarball from the standard confidential image dependencies -- those components now live exclusively in the CoCo addon image. NVIDIA confidential images retain them until the NVIDIA addon split lands. Signed-off-by: Fabiano FidĂȘncio Assisted-by: Cursor --- .../osbuilder/rootfs-builder/ubuntu/config.sh | 4 +- tools/packaging/guest-image/build_image.sh | 17 ++- .../kata-deploy/local-build/Makefile | 9 +- .../local-build/kata-deploy-binaries.sh | 136 ++++++++++++++++-- 4 files changed, 146 insertions(+), 20 deletions(-) diff --git a/tools/osbuilder/rootfs-builder/ubuntu/config.sh b/tools/osbuilder/rootfs-builder/ubuntu/config.sh index 9a5f9db9ff..45b1dd0d5f 100644 --- a/tools/osbuilder/rootfs-builder/ubuntu/config.sh +++ b/tools/osbuilder/rootfs-builder/ubuntu/config.sh @@ -11,11 +11,11 @@ OS_NAME=ubuntu # This should be Ubuntu's code name, e.g. "focal" (Focal Fossa) for 20.04 OS_VERSION=${OS_VERSION:-""} [[ -z "${OS_VERSION}" ]] && echo "OS_VERSION is required, but was not set" && exit 1 -PACKAGES="chrony iptables dbus" +PACKAGES="chrony iptables dbus cryptsetup-bin" # shellcheck disable=SC2154 [[ "${AGENT_INIT}" = no ]] && PACKAGES+=" init" # CDH secure storage feature requires these tools in the guest -[[ "${CONFIDENTIAL_GUEST:-no}" = "yes" ]] && PACKAGES+=" cryptsetup-bin e2fsprogs" +[[ "${CONFIDENTIAL_GUEST:-no}" = "yes" ]] && PACKAGES+=" e2fsprogs" # shellcheck disable=SC2154 [[ "${SECCOMP}" = yes ]] && PACKAGES+=" libseccomp2" [[ "$(uname -m)" = "s390x" ]] && PACKAGES+=" libcurl4 libnghttp2-14" diff --git a/tools/packaging/guest-image/build_image.sh b/tools/packaging/guest-image/build_image.sh index bc93e0f0ea..423366e357 100755 --- a/tools/packaging/guest-image/build_image.sh +++ b/tools/packaging/guest-image/build_image.sh @@ -75,8 +75,17 @@ build_image() { info "Build image" info "image os: ${os_name}" info "image os version: ${os_version}" + + # The label used for BUILD_VARIANT (and therefore the emitted + # root_hash_.txt file) is normally the image filename suffix. + # The base image, however, has an empty suffix (it is shipped as + # kata-containers.img) yet may still be built measured. Callers can set + # ROOT_HASH_VARIANT to give that measured base a dedicated root-hash label + # (e.g. "base") without changing the image filename. + local build_variant="${ROOT_HASH_VARIANT:-${image_initrd_suffix}}" + make image \ - BUILD_VARIANT="${image_initrd_suffix}" \ + BUILD_VARIANT="${build_variant}" \ DISTRO="${os_name}" \ DEBUG="${DEBUG:-}" \ USE_DOCKER="1" \ @@ -94,9 +103,9 @@ build_image() { fi mv -f "kata-containers.img" "${install_dir}/${artifact_name}" - if [[ -e "root_hash_${image_initrd_suffix}.txt" ]]; then - info "Copying root hash file for variant: ${image_initrd_suffix} ${PWD}" - cp "root_hash_${image_initrd_suffix}.txt" "${install_dir}/" + if [[ -e "root_hash_${build_variant}.txt" ]]; then + info "Copying root hash file for variant: ${build_variant} ${PWD}" + cp "root_hash_${build_variant}.txt" "${install_dir}/" fi ( cd "${install_dir}" diff --git a/tools/packaging/kata-deploy/local-build/Makefile b/tools/packaging/kata-deploy/local-build/Makefile index 5af4a6e989..97496738f4 100644 --- a/tools/packaging/kata-deploy/local-build/Makefile +++ b/tools/packaging/kata-deploy/local-build/Makefile @@ -37,6 +37,7 @@ BASE_TARBALLS = serial-targets \ virtiofsd-tarball BASE_SERIAL_TARBALLS = rootfs-image-tarball \ rootfs-image-confidential-tarball \ + rootfs-image-coco-addon-tarball \ rootfs-image-mariner-tarball \ rootfs-initrd-confidential-tarball \ rootfs-initrd-tarball \ @@ -50,6 +51,7 @@ BASE_TARBALLS = serial-targets \ shim-v2-rust-tarball \ virtiofsd-tarball BASE_SERIAL_TARBALLS = rootfs-image-tarball \ + rootfs-image-coco-addon-tarball \ rootfs-initrd-tarball else ifeq ($(ARCH), aarch64) BASE_TARBALLS = serial-targets \ @@ -63,6 +65,7 @@ BASE_TARBALLS = serial-targets \ virtiofsd-tarball BASE_SERIAL_TARBALLS = rootfs-image-tarball \ rootfs-image-confidential-tarball \ + rootfs-image-coco-addon-tarball \ rootfs-cca-confidential-image-tarball \ rootfs-cca-confidential-initrd-tarball \ rootfs-initrd-tarball @@ -268,10 +271,14 @@ DEPS := agent-tarball rootfs-image-tarball: $(DEPS) ${MAKE} $@-build -DEPS := agent-tarball pause-image-tarball coco-guest-components-tarball kernel-tarball +DEPS := agent-tarball kernel-tarball rootfs-image-confidential-tarball: $(DEPS) ${MAKE} $@-build +DEPS := pause-image-tarball coco-guest-components-tarball +rootfs-image-coco-addon-tarball: $(DEPS) + ${MAKE} $@-build + DEPS := agent-tarball rootfs-image-mariner-tarball: $(DEPS) ${MAKE} $@-build diff --git a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh index 7aa3b20d49..a6ee51cf3e 100755 --- a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh +++ b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh @@ -135,6 +135,7 @@ options: stratovirt rootfs-image rootfs-image-confidential + rootfs-image-coco-addon rootfs-image-mariner rootfs-initrd rootfs-initrd-confidential @@ -187,7 +188,7 @@ cleanup_and_fail_shim_v2_specifics() { local extra_tarballs="${3:-}" local tarball_dir="${repo_root_dir}/tools/packaging/kata-deploy/local-build/build" - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do local root_hash_file="${tarball_dir}/${component}-root_hash_${variant}.txt" [[ -f "${root_hash_file}" ]] && rm -f "${root_hash_file}" done @@ -217,8 +218,15 @@ install_cached_shim_v2_tarball_get_root_hash() { local tarball_dir="${repo_root_dir}/tools/packaging/kata-deploy/local-build/build" local root_hash_basedir="./opt/kata/share/kata-containers/" - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do - local image_conf_tarball="kata-static-rootfs-image-${variant}.tar.zst" + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do + # The measured base image ships as kata-static-rootfs-image.tar.zst + # (no variant suffix), but carries its root hash under the "base" label. + local image_conf_tarball + if [[ "${variant}" == "base" ]]; then + image_conf_tarball="kata-static-rootfs-image.tar.zst" + else + image_conf_tarball="kata-static-rootfs-image-${variant}.tar.zst" + fi local tarball_path="${tarball_dir}/${image_conf_tarball}" local root_hash_path="${root_hash_basedir}root_hash_${variant}.txt" @@ -238,7 +246,7 @@ install_cached_shim_v2_tarball_compare_root_hashes() { local found_any="" local tarball_dir="${repo_root_dir}/tools/packaging/kata-deploy/local-build/build" - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do local image_root_hash="${tarball_dir}/root_hash_${variant}.txt" local cached_root_hash="${component}-root_hash_${variant}.txt" @@ -453,12 +461,11 @@ install_image() { latest_artefact+="-$(get_latest_nvidia_ctk_version)" latest_artefact+="-$(get_latest_nvidia_nvrc_version)" latest_artefact+="-$(get_latest_nvidia_nvat_version)" + latest_artefact+="-$(get_latest_coco_guest_components_artefact_and_builder_image_version)" + latest_artefact+="-$(get_latest_pause_image_artefact_and_builder_image_version)" else latest_artefact+="-$(get_latest_kernel_artefact_and_builder_image_version)" fi - - latest_artefact+="-$(get_latest_coco_guest_components_artefact_and_builder_image_version)" - latest_artefact+="-$(get_latest_pause_image_artefact_and_builder_image_version)" fi if [[ "${variant}" == "nvidia-gpu" ]]; then @@ -469,6 +476,19 @@ install_image() { latest_artefact+="-$(get_latest_nvidia_nvrc_version)" fi + # The base guest image (empty variant) is built as a measured rootfs so + # that confidential configurations can dm-verity-protect it; non-confidential + # configurations simply boot its data partition unverified. Reflect the + # measured build (and the kernel it is tied to, since measured boot depends + # on it) in the cache key, and emit the root hash under a dedicated "base" + # label so it never collides with the legacy confidential image hash. + local root_hash_variant="${variant}" + if [[ -z "${variant}" && "${MEASURED_ROOTFS:-no}" == "yes" ]]; then + root_hash_variant="base" + latest_artefact+="-measured-$(get_latest_kernel_artefact_and_builder_image_version)" + fi + export ROOT_HASH_VARIANT="${root_hash_variant}" + latest_builder_image="" install_cached_tarball_component \ @@ -482,7 +502,11 @@ install_image() { info "Create image" if [[ -n "${variant}" ]]; then - if [[ "${variant}" == *confidential ]]; then + # NVIDIA confidential images still bake CoCo components into the + # rootfs (until the NVIDIA addon split lands). Standard + # confidential images no longer need them -- CoCo components are + # built as a separate addon image (rootfs-image-coco-addon). + if [[ "${variant}" == "nvidia-gpu-confidential" ]]; then COCO_GUEST_COMPONENTS_TARBALL="$(get_coco_guest_components_tarball_path)" export COCO_GUEST_COMPONENTS_TARBALL PAUSE_IMAGE_TARBALL="$(get_pause_image_tarball_path)" @@ -518,7 +542,29 @@ install_image() { "${rootfs_builder}" --osname="${os_name}" --osversion="${os_version}" --imagetype=image --prefix="${prefix}" --destdir="${destdir}" --image_initrd_suffix="${variant}" } +#Install the base guest image +# +# The base image (kata-containers.img) is shared by both non-confidential and +# confidential configurations. It is built once as a measured rootfs (dm-verity +# hash partition + root hash emitted under the "base" label). Confidential +# configurations enforce that hash via the kernel command line, while +# non-confidential configurations ignore it and boot the data partition +# directly. Measured rootfs is not used on s390x (Secure Execution measures the +# guest through a different mechanism), so the base stays unmeasured there. +install_image_base() { + if [[ "${ARCH}" == "s390x" ]]; then + export MEASURED_ROOTFS="no" + else + export MEASURED_ROOTFS="yes" + fi + install_image +} + #Install guest image for confidential guests +# +# CoCo guest components are no longer baked into this image. +# They are built separately as a CoCo addon image +# (rootfs-image-coco-addon) and attached as an extra block device. install_image_confidential() { export CONFIDENTIAL_GUEST="yes" if [[ "${ARCH}" == "s390x" ]]; then @@ -529,6 +575,64 @@ install_image_confidential() { install_image "confidential" } +#Install CoCo addon image (erofs+verity, contains CoCo guest components + pause) +install_image_coco_addon() { + local component="rootfs-image-coco-addon" + + local coco_last_commit + coco_last_commit="$(get_latest_coco_guest_components_artefact_and_builder_image_version)" + local pause_last_commit + pause_last_commit="$(get_latest_pause_image_artefact_and_builder_image_version)" + + latest_artefact="$(get_kata_version)-coco-addon-${coco_last_commit}-${pause_last_commit}" + latest_builder_image="" + + install_cached_tarball_component \ + "${component}" \ + "${latest_artefact}" \ + "${latest_builder_image}" \ + "${final_tarball_name}" \ + "${final_tarball_path}" \ + && return 0 + + info "Create CoCo addon image" + + # Use a temp dir under the repo root so the path is valid both inside + # the outer build-kata-deploy container and in the nested image-builder + # container (Docker-in-Docker mounts use host paths). + local addon_rootfs + addon_rootfs="$(mktemp -d "${repo_root_dir}/.coco-addon-rootfs.XXXX")" + + COCO_GUEST_COMPONENTS_TARBALL="$(get_coco_guest_components_tarball_path)" + PAUSE_IMAGE_TARBALL="$(get_pause_image_tarball_path)" + + info "Unpacking CoCo guest components into addon rootfs" + tar --zstd -xvf "${COCO_GUEST_COMPONENTS_TARBALL}" -C "${addon_rootfs}" + + info "Unpacking pause image into addon rootfs" + tar --zstd -xvf "${PAUSE_IMAGE_TARBALL}" -C "${addon_rootfs}" + + local install_dir="${destdir}/${prefix}/share/kata-containers/" + mkdir -p "${install_dir}" + + local image_builder="${repo_root_dir}/tools/osbuilder/image-builder/image_builder.sh" + + export USE_DOCKER="1" + export BUILD_VARIANT="coco-addon" + export FS_TYPE="erofs" + export MEASURED_ROOTFS="yes" + export SKIP_DAX_HEADER="yes" + export SKIP_ROOTFS_CHECK="yes" + + "${image_builder}" -o "${install_dir}/kata-containers-coco-addon.img" "${addon_rootfs}" + + if [[ -e "${install_dir}/root_hash_coco-addon.txt" ]]; then + info "Root hash file: ${install_dir}/root_hash_coco-addon.txt" + fi + + rm -rf "${addon_rootfs}" +} + #Install cbl-mariner guest image install_image_mariner() { export IMAGE_SIZE_ALIGNMENT_MB=2 @@ -1054,9 +1158,13 @@ install_nydus() { # Shared helper: extract measured-rootfs root hashes from confidential image tarballs. # These are needed by the Rust runtime (runtime-rs) at build time for dm-verity. _collect_root_hashes() { - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do + # The measured base image ships as kata-static-rootfs-image.tar.zst + # (no variant suffix), but carries its root hash under the "base" label. + local tarball_glob="kata-static-rootfs-image-${variant}.tar.zst" + [[ "${variant}" == "base" ]] && tarball_glob="kata-static-rootfs-image.tar.zst" local image_conf_tarball - image_conf_tarball="$(find "${workdir}" -maxdepth 1 -name "kata-static-rootfs-image-${variant}.tar.zst" 2>/dev/null | head -n 1)" + image_conf_tarball="$(find "${workdir}" -maxdepth 1 -name "${tarball_glob}" 2>/dev/null | head -n 1)" # Only one variant may be built at a time so we need to # skip one or the other if not available. [[ -f "${image_conf_tarball}" ]] || continue @@ -1498,10 +1606,12 @@ handle_build() { stratovirt) install_stratovirt ;; - rootfs-image) install_image ;; + rootfs-image) install_image_base ;; rootfs-image-confidential) install_image_confidential ;; + rootfs-image-coco-addon) install_image_coco_addon ;; + rootfs-image-mariner) install_image_mariner ;; rootfs-initrd) install_initrd ;; @@ -1571,7 +1681,7 @@ handle_build() { ;; shim-v2-go|shim-v2-rust) if [[ "${MEASURED_ROOTFS}" == "yes" ]]; then - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do [[ -f "${workdir}/root_hash_${variant}.txt" ]] && mv "${workdir}/root_hash_${variant}.txt" "${workdir}/${build_target}-root_hash_${variant}.txt" done fi @@ -1640,7 +1750,7 @@ handle_build() { shim-v2-go|shim-v2-rust) if [[ "${MEASURED_ROOTFS}" == "yes" ]]; then local found_any="" - for variant in confidential nvidia-gpu nvidia-gpu-confidential; do + for variant in base confidential coco-addon nvidia-gpu nvidia-gpu-confidential; do # The variants could be built independently we need to check if # they exist and then push them to the registry [[ -f "${workdir}/${build_target}-root_hash_${variant}.txt" ]] && files_to_push+=("${build_target}-root_hash_${variant}.txt") && found_any="yes"