mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-08-09 16:20:59 +00:00
build: seal CoCo extension verity params into SE image
The IBM SEL composable image (boot-image-se-runtime-rs-tarball) was
sealing a bare `kata.extension.coco.verity_params` key into the kernel
command line with no value, leaving the CoCo extension unmeasured on
other architectures where the extension image carries a dm-verity hash
partition.
Now `root_hash_coco-extension.txt` is published by guest-components
as part of the `coco-extension-disk` OCI artifact (pinned in versions.yaml)
and is bundled inside `kata-static-rootfs-image-coco-extension.tar.zst`.
Changes:
- Makefile: add `rootfs-image-coco-extension-tarball` to the DEPS of
`boot-image-se-runtime-rs-tarball` so the root hash is available
before the SE image is sealed.
- build_se_image.sh: extract `root_hash_coco-extension.txt` from the
extension tarball (mirroring `_collect_root_hashes`) and export it as
COCO_VERITY_PARAMS when SE_COMPOSABLE=yes. Left unset when absent.
- lib_se.sh: emit `kata.extension.coco.verity_params=${COCO_VERITY_PARAMS}`
when set.
- lib.sh (k8s tests): export COCO_VERITY_PARAMS from the installed root
hash file before calling repack_secure_image.
The shim-v2-rust-tarball path already works via _collect_root_hashes
and the all-parallel → SHIM_TARBALLS build ordering.
Update docs to cover both the qemu-se and qemu-se-runtime-rs build
paths, and extend the composable-vm-images security model with the IBM
SE genprotimg sealing mechanism and a general unmeasured-extensions note.
Generated-by: IBM Bob
Signed-off-by: Hyounggyu Choi <Hyounggyu.Choi@ibm.com>
This commit is contained in:
@@ -647,6 +647,27 @@ Confidential Containers:
|
||||
without changing the measurement, which would be detected during
|
||||
attestation.
|
||||
|
||||
- IBM Secure Execution achieves equivalent integrity through a different mechanism.
|
||||
`genprotimg` seals the full kernel command line — including
|
||||
`kata.extension.coco.verity_params=root_hash=...,salt=...,data_blocks=...,...`
|
||||
— into the SE image header at build time, encrypted under the host key. The sealed
|
||||
contents are integrity-protected and cannot be altered without rebuilding the image.
|
||||
The build-time dependency on
|
||||
`rootfs-image-coco-extension-tarball` ensures the root hash published at the
|
||||
pinned `versions.yaml` commit is locked into the SE image at creation time.
|
||||
Substituting the extension image at runtime would be detected by dm-verity verification
|
||||
during boot.
|
||||
|
||||
- **Unmeasured extensions** — when `kata.extension.coco.verity_params` carries no
|
||||
value (a bare key), the mount script performs a raw mount without dm-verity
|
||||
verification. This is the correct path when the extension image was intentionally
|
||||
built without a hash partition (e.g. because the surrounding platform already
|
||||
provides a different integrity guarantee). The mount script cross-checks the
|
||||
cmdline against the on-disk partition layout to prevent a measured extension from
|
||||
being silently downgraded: if a hash partition is present on disk but
|
||||
`verity_params` is bare, the mount is refused and the VM shuts down. See the
|
||||
[integrity policy table](#mount-script) above.
|
||||
|
||||
- **Mount failure = VM shutdown** — `OnFailure=poweroff.target` ensures the
|
||||
VM does not proceed with missing or tampered components.
|
||||
|
||||
|
||||
@@ -70,16 +70,12 @@ kata-ubuntu-20.04-confidential.initrd
|
||||
kata-ubuntu-latest.image
|
||||
kata-ubuntu-latest-confidential.image
|
||||
vmlinux-6.1.62-121
|
||||
vmlinux-6.1.62-121-confidential
|
||||
vmlinux.container
|
||||
vmlinux-confidential.container
|
||||
vmlinuz-6.1.62-121
|
||||
vmlinuz-6.1.62-121-confidential
|
||||
vmlinuz.container
|
||||
vmlinuz-confidential.container
|
||||
```
|
||||
|
||||
The output indicates the deployment of the kernel (`vmlinux-6.1.62-121-confidential`, though the version
|
||||
The output indicates the deployment of the kernel (`vmlinux-6.1.62-121`, though the version
|
||||
may vary at the time of testing), rootfs-image (`kata-ubuntu-latest-confidential.image`), and rootfs-initrd (`kata-ubuntu-20.04-confidential.initrd`).
|
||||
In this scenario, the available kernel and initrd can be utilized for a secure image.
|
||||
However, if any of these components are absent, they must be built from the
|
||||
@@ -89,18 +85,18 @@ However, if any of these components are absent, they must be built from the
|
||||
$ # Assume that the project is cloned at $GOPATH/src/github.com/kata-containers
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ make rootfs-initrd-confidential-tarball
|
||||
$ tar --zstd -tf build/kata-static-kernel-confidential.tar.zst | grep vmlinuz
|
||||
./opt/kata/share/kata-containers/vmlinuz-confidential.container
|
||||
./opt/kata/share/kata-containers/vmlinuz-6.7-136-confidential
|
||||
$ tar --zstd -tf build/kata-static-kernel.tar.zst | grep vmlinuz
|
||||
./opt/kata/share/kata-containers/vmlinuz.container
|
||||
./opt/kata/share/kata-containers/vmlinuz-6.7-136
|
||||
$ kernel_version=6.7-136
|
||||
$ tar --zstd -tf build/kata-static-rootfs-initrd-confidential.tar.zst | grep initrd
|
||||
./opt/kata/share/kata-containers/kata-containers-initrd-confidential.img
|
||||
./opt/kata/share/kata-containers/kata-ubuntu-20.04-confidential.initrd
|
||||
$ mkdir artifacts
|
||||
$ tar --zstd -xvf build/kata-static-kernel-confidential.tar.zst -C artifacts ./opt/kata/share/kata-containers/vmlinuz-${kernel_version}-confidential
|
||||
$ tar --zstd -xvf build/kata-static-kernel.tar.zst -C artifacts ./opt/kata/share/kata-containers/vmlinuz-${kernel_version}
|
||||
$ tar --zstd -xvf build/kata-static-rootfs-initrd-confidential.tar.zst -C artifacts ./opt/kata/share/kata-containers/kata-ubuntu-20.04-confidential.initrd
|
||||
$ ls artifacts/opt/kata/share/kata-containers/
|
||||
kata-ubuntu-20.04-confidential.initrd vmlinuz-${kernel_version}-confidential
|
||||
kata-ubuntu-20.04-confidential.initrd vmlinuz-${kernel_version}
|
||||
```
|
||||
|
||||
3. Secure Image Generation Tool
|
||||
@@ -150,13 +146,25 @@ and two certificates and one revocation list at `$HOME/certificates`:
|
||||
- `DigiCert` intermediate CA certificate as `DigiCertCA.crt`
|
||||
- IBM Z host key certificate revocation list as `ibm-z-host-key-gen2.crl`
|
||||
|
||||
There are two distinct image variants, corresponding to the two supported
|
||||
runtime classes:
|
||||
|
||||
- **`qemu-se`** (Go runtime) — uses a monolithic confidential initrd that
|
||||
bundles all CoCo guest components.
|
||||
- **`qemu-se-runtime-rs`** (Rust runtime, composable) — uses a lean base
|
||||
initrd plus a separately-attached
|
||||
[CoCo extension image](../design/composable-vm-images.md).
|
||||
|
||||
The instructions below apply to both variants unless a variant is called out
|
||||
explicitly.
|
||||
|
||||
you can construct a secure image using the following procedure:
|
||||
|
||||
```
|
||||
$ # Change a directory to the project root
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ host_key_document=$HOME/host-key-document/HKD-0000-0000000.crt
|
||||
$ kernel_image=artifacts/opt/kata/share/kata-containers/vmlinuz-${kernel_version}-confidential
|
||||
$ kernel_image=artifacts/opt/kata/share/kata-containers/vmlinuz-${kernel_version}
|
||||
$ initrd_image=artifacts/opt/kata/share/kata-containers/kata-ubuntu-20.04-confidential.initrd
|
||||
$ echo "panic=1 scsi_mod.scan=none swiotlb=262144 agent.log=debug" > parmfile
|
||||
$ genprotimg --host-key-document=${host_key_document} \
|
||||
@@ -183,10 +191,12 @@ $ genprotimg --host-key-document=${host_key_document} \
|
||||
--cert=${cacert} --cert=${signcert} --crl=${crl} --parmfile=parmfile
|
||||
```
|
||||
|
||||
The steps with no verification, including the dependencies for the kernel and initrd,
|
||||
can be easily accomplished by issuing the following make target:
|
||||
The steps with no verification, including the dependencies for the kernel and
|
||||
initrd, can be easily accomplished by issuing the following make target.
|
||||
|
||||
```
|
||||
=== `qemu-se` (Go runtime, monolithic)
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ mkdir hkd_dir && cp $host_key_document hkd_dir
|
||||
$ HKD_PATH=hkd_dir SE_KERNEL_PARAMS="agent.log=debug" make boot-image-se-tarball
|
||||
@@ -194,7 +204,29 @@ $ ls build/kata-static-boot-image-se.tar.zst
|
||||
build/kata-static-boot-image-se.tar.zst
|
||||
```
|
||||
|
||||
`SE_KERNEL_PARAMS` could be used to add any extra kernel parameters. If no additional kernel configuration is required, this can be omitted.
|
||||
=== `qemu-se-runtime-rs` (Rust runtime, composable)
|
||||
|
||||
This target automatically builds `rootfs-image-coco-extension-tarball` as a
|
||||
prerequisite. The CoCo extension image is pinned to the commit in
|
||||
`versions.yaml` (`.externals.coco-guest-components.version`), and its
|
||||
dm-verity root hash (`root_hash_coco-extension.txt`) is bundled inside the
|
||||
extension tarball and published by the [guest-components](https://github.com/confidential-containers/guest-components) project. The build
|
||||
extracts this hash and seals it into the SE kernel command line as
|
||||
`kata.extension.coco.verity_params=root_hash=...,salt=...,data_blocks=...,...`
|
||||
via `genprotimg`. Any substitution of the extension image is therefore
|
||||
detected at boot time — the sealed hash will not match.
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ mkdir hkd_dir && cp $host_key_document hkd_dir
|
||||
$ HKD_PATH=hkd_dir SE_KERNEL_PARAMS="agent.log=debug" make boot-image-se-runtime-rs-tarball
|
||||
$ ls build/kata-static-boot-image-se-runtime-rs.tar.zst build/kata-static-rootfs-image-coco-extension.tar.zst
|
||||
build/kata-static-boot-image-se-runtime-rs.tar.zst
|
||||
build/kata-static-rootfs-image-coco-extension.tar.zst
|
||||
```
|
||||
|
||||
`SE_KERNEL_PARAMS` can be used to inject extra kernel parameters into both
|
||||
variants. It can be omitted if no additional configuration is needed.
|
||||
|
||||
In production, you could build an image by running the same command, but with the
|
||||
following environment variables for key verification:
|
||||
@@ -327,15 +359,19 @@ please refer to the
|
||||
for confidential containers.
|
||||
|
||||
|
||||
```
|
||||
The following examples show the build commands for each runtime class.
|
||||
|
||||
=== `qemu-se` (Go runtime, monolithic)
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ host_key_document=$HOME/host-key-document/HKD-0000-0000000.crt
|
||||
$ mkdir hkd_dir && cp $host_key_document hkd_dir
|
||||
$ # kernel-confidential and rootfs-initrd-confidential are built automactially by the command below
|
||||
$ # kernel and rootfs-initrd-confidential are built automatically by the command below
|
||||
$ HKD_PATH=hkd_dir SE_KERNEL_PARAMS="agent.log=debug" make boot-image-se-tarball
|
||||
$ make qemu-tarball
|
||||
$ make virtiofsd-tarball
|
||||
$ make shim-v2-tarball
|
||||
$ make shim-v2-go-tarball
|
||||
$ mkdir kata-artifacts
|
||||
$ build_dir=$(readlink -f build)
|
||||
$ cp -r $build_dir/*.tar.zst kata-artifacts
|
||||
@@ -343,12 +379,40 @@ $ ls -1 kata-artifacts
|
||||
kata-static-agent.tar.zst
|
||||
kata-static-boot-image-se.tar.zst
|
||||
kata-static-coco-guest-components.tar.zst
|
||||
kata-static-kernel-confidential-modules.tar.zst
|
||||
kata-static-kernel-confidential.tar.zst
|
||||
kata-static-kernel.tar.zst
|
||||
kata-static-pause-image.tar.zst
|
||||
kata-static-qemu.tar.zst
|
||||
kata-static-rootfs-initrd-confidential.tar.zst
|
||||
kata-static-shim-v2.tar.zst
|
||||
kata-static-shim-v2-go.tar.zst
|
||||
kata-static-virtiofsd.tar.zst
|
||||
$ ./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
|
||||
```
|
||||
|
||||
=== `qemu-se-runtime-rs` (Rust runtime, composable)
|
||||
|
||||
`boot-image-se-runtime-rs-tarball` automatically builds the CoCo extension
|
||||
tarball as a prerequisite, so `kata-static-rootfs-image-coco-extension.tar.zst`
|
||||
is produced alongside the SE image and must be included in the payload.
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers
|
||||
$ host_key_document=$HOME/host-key-document/HKD-0000-0000000.crt
|
||||
$ mkdir hkd_dir && cp $host_key_document hkd_dir
|
||||
$ # kernel and rootfs-initrd are built automatically by the command below
|
||||
$ HKD_PATH=hkd_dir SE_KERNEL_PARAMS="agent.log=debug" make boot-image-se-runtime-rs-tarball
|
||||
$ make qemu-tarball
|
||||
$ make virtiofsd-tarball
|
||||
$ make shim-v2-rust-tarball
|
||||
$ mkdir kata-artifacts
|
||||
$ build_dir=$(readlink -f build)
|
||||
$ cp -r $build_dir/*.tar.zst kata-artifacts
|
||||
$ ls -1 kata-artifacts
|
||||
kata-static-boot-image-se-runtime-rs.tar.zst
|
||||
kata-static-kernel.tar.zst
|
||||
kata-static-qemu.tar.zst
|
||||
kata-static-rootfs-image-coco-extension.tar.zst
|
||||
kata-static-rootfs-initrd.tar.zst
|
||||
kata-static-shim-v2-rust.tar.zst
|
||||
kata-static-virtiofsd.tar.zst
|
||||
$ ./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
|
||||
```
|
||||
|
||||
@@ -416,6 +416,15 @@ set_metadata_annotation() {
|
||||
fi
|
||||
if [[ "${KATA_HYPERVISOR}" == "qemu-se-runtime-rs" ]]; then
|
||||
export SE_COMPOSABLE="yes"
|
||||
# Seed the CoCo extension verity params so the rebuilt SE image seals
|
||||
# the actual root hash into its kernel cmdline. The file is absent on
|
||||
# s390x (unmeasured extension); the bare-key fallback in lib_se.sh
|
||||
# handles that case correctly.
|
||||
local root_hash_file="/opt/kata/share/kata-containers/root_hash_coco-extension.txt"
|
||||
if [[ -f "${root_hash_file}" ]]; then
|
||||
COCO_VERITY_PARAMS="$(< "${root_hash_file}")"
|
||||
export COCO_VERITY_PARAMS
|
||||
fi
|
||||
fi
|
||||
repack_secure_image "${value}" "${IBM_SE_CREDS_DIR}" "true"
|
||||
fi
|
||||
|
||||
@@ -73,6 +73,21 @@ build_image() {
|
||||
for tarball_id in kernel "${initrd_tarball_id}"; do
|
||||
tar --zstd -xvf "kata-static-${tarball_id}.tar.zst" -C "${image_source_dir}"
|
||||
done
|
||||
|
||||
# For the composable path, extract the CoCo extension root hash so the
|
||||
# sealed SE kernel cmdline carries the verity params.
|
||||
# COCO_VERITY_PARAMS must be set; lib_se.sh will die if it is absent.
|
||||
if [[ "${SE_COMPOSABLE}" == "yes" ]]; then
|
||||
local coco_ext_tarball="kata-static-rootfs-image-coco-extension.tar.zst"
|
||||
local root_hash_path="./opt/kata/share/kata-containers/root_hash_coco-extension.txt"
|
||||
tar --zstd -tf "${coco_ext_tarball}" "${root_hash_path}" >/dev/null 2>&1 \
|
||||
|| die "root_hash_coco-extension.txt not found in ${coco_ext_tarball}"
|
||||
local root_hash_tmp
|
||||
root_hash_tmp="$(tar --zstd -xOf "${coco_ext_tarball}" "${root_hash_path}")"
|
||||
root_hash_tmp="${root_hash_tmp%$'\r'}"
|
||||
[[ -n "${root_hash_tmp}" ]] || die "Empty root_hash_coco-extension.txt in ${coco_ext_tarball}"
|
||||
export COCO_VERITY_PARAMS="${root_hash_tmp}"
|
||||
fi
|
||||
popd
|
||||
|
||||
protimg_source_dir="${image_source_dir}${prefix}/share/kata-containers"
|
||||
|
||||
@@ -74,10 +74,10 @@ EOF
|
||||
return 1
|
||||
fi
|
||||
|
||||
cmdline="${kernel_params} panic=1 scsi_mod.scan=none swiotlb=262144 agent.debug_console agent.debug_console_vport=1026"
|
||||
if [[ "${SE_COMPOSABLE:-no}" == "yes" ]]; then
|
||||
cmdline="${kernel_params} panic=1 scsi_mod.scan=none swiotlb=262144 agent.debug_console agent.debug_console_vport=1026 kata.extension.coco.verity_params"
|
||||
else
|
||||
cmdline="${kernel_params} panic=1 scsi_mod.scan=none swiotlb=262144 agent.debug_console agent.debug_console_vport=1026"
|
||||
[[ -n "${COCO_VERITY_PARAMS:-}" ]] || die "COCO_VERITY_PARAMS must be set for composable SE image builds"
|
||||
cmdline+=" kata.extension.coco.verity_params=${COCO_VERITY_PARAMS}"
|
||||
fi
|
||||
parmfile="$(mktemp --suffix=-cmdline)"
|
||||
echo "${cmdline}" > "${parmfile}"
|
||||
|
||||
@@ -319,7 +319,7 @@ boot-image-se-tarball: $(DEPS)
|
||||
ifeq ($(FAKE_SE_IMAGE),true)
|
||||
DEPS :=
|
||||
else
|
||||
DEPS := kernel-tarball rootfs-initrd-tarball
|
||||
DEPS := kernel-tarball rootfs-initrd-tarball rootfs-image-coco-extension-tarball
|
||||
endif
|
||||
boot-image-se-runtime-rs-tarball: $(DEPS)
|
||||
${MAKE} $@-build
|
||||
|
||||
@@ -279,7 +279,7 @@ externals:
|
||||
coco-guest-components:
|
||||
description: "Provides attested key unwrapping for image decryption"
|
||||
url: "https://github.com/confidential-containers/guest-components/"
|
||||
version: "fff3a966b7b1d1654d172a7cd81c0f563721ff0b"
|
||||
version: "d4dce5ce62294cfa741225f7e5b4527ea276f326"
|
||||
# Scratch OCI container image (guest-components "Publish OCI container
|
||||
# image" step). Consumed by monolithic confidential rootfs builds.
|
||||
# yamllint disable-line rule:line-length
|
||||
|
||||
Reference in New Issue
Block a user