From 5ec2634fe7668d43c10c1b64603e10023f2fd4fb Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Tue, 16 Jun 2026 15:44:14 +0800 Subject: [PATCH] tests: Add E2E test for erofs dm-verity integrity in CI tests Add k8s-erofs-dmverity.bats integration test that verifies dm-verity protected EROFS layers work end-to-end, and register the integrity mode in the CoCo test matrix. This commit introduces two new files to enable it: - k8s-erofs-dmverity.bats - pod-erofs-dmverity-probe.yaml Signed-off-by: Alex Lyn --- .github/workflows/run-kata-coco-tests.yaml | 1 + .../kubernetes/k8s-erofs-dmverity.bats | 73 +++++++++++++++++++ .../kubernetes/run_kubernetes_tests.sh | 1 + .../pod-erofs-dmverity-probe.yaml | 19 +++++ 4 files changed, 94 insertions(+) create mode 100644 tests/integration/kubernetes/k8s-erofs-dmverity.bats create mode 100644 tests/integration/kubernetes/runtimeclass_workloads/pod-erofs-dmverity-probe.yaml diff --git a/.github/workflows/run-kata-coco-tests.yaml b/.github/workflows/run-kata-coco-tests.yaml index f240775a78..466bca7088 100644 --- a/.github/workflows/run-kata-coco-tests.yaml +++ b/.github/workflows/run-kata-coco-tests.yaml @@ -412,6 +412,7 @@ jobs: erofs-mode: - disk - memory + - integrity concurrency: group: ${{ github.workflow }}-${{ github.job }}-${{ github.event.pull_request.number || github.ref }}-${{ toJSON(matrix) }} cancel-in-progress: true diff --git a/tests/integration/kubernetes/k8s-erofs-dmverity.bats b/tests/integration/kubernetes/k8s-erofs-dmverity.bats new file mode 100644 index 0000000000..c052ab08ee --- /dev/null +++ b/tests/integration/kubernetes/k8s-erofs-dmverity.bats @@ -0,0 +1,73 @@ +#!/usr/bin/env bats +# +# Copyright (c) 2026 Ant Group +# +# SPDX-License-Identifier: Apache-2.0 +# +# Verifies that, when the erofs snapshotter is configured in integrity mode, +# kata-agent activates dm-verity for every EROFS layer in the guest rootfs. +# +# Verification strategy: +# We assert that dmesg shows BOTH: +# * "device-mapper: verity: sha256 using ..." — emitted by +# drivers/md/dm-verity-target.c when a verity target is loaded. +# * "erofs (device dm-N): mounted ..." — emitted by +# fs/erofs/super.c on a successful mount. +# The presence of both implies each EROFS layer went through a +# dm-verity device on the I/O path. + +load "${BATS_TEST_DIRNAME}/../../common.bash" +load "${BATS_TEST_DIRNAME}/lib.sh" +load "${BATS_TEST_DIRNAME}/tests_common.sh" + +setup() { + # Hard gate: only run on the dedicated integrity CI leg. + [[ "${SNAPSHOTTER:-}" == "erofs" ]] || skip "needs SNAPSHOTTER=erofs" + [[ "${EROFS_SNAPSHOTTER_MODE:-}" == "integrity" ]] \ + || skip "needs EROFS_SNAPSHOTTER_MODE=integrity" + + setup_common || die "setup_common failed" + + pod_name="erofs-dmverity-probe" + yaml_file="${pod_config_dir}/pod-erofs-dmverity-probe.yaml" +} + +@test "EROFS layers are mounted via dm-verity inside the guest" { + create_container_timeout=180 + set_metadata_annotation "${yaml_file}" \ + "io.katacontainers.config.runtime.create_container_timeout" \ + "${create_container_timeout}" + kubectl apply -f "${yaml_file}" + kubectl wait --for=condition=Ready --timeout="${create_container_timeout}s" pod "${pod_name}" + + # Read the guest kernel ring buffer and require both a dm-verity target + # load record and an EROFS mount record. Limit to the last 100 lines. + # shellcheck disable=SC2016 # variables are expanded inside the pod's shell + run kubectl exec "${pod_name}" -- sh -c ' + log=$(dmesg 2>&1 | tail -n 100) + verity_lines=$(printf "%s\n" "$log" | grep -c "device-mapper: verity") + erofs_lines=$(printf "%s\n" "$log" | grep -cE "erofs \(device dm-[0-9]+\): mounted") + echo "verity_lines=${verity_lines} erofs_lines=${erofs_lines}" + if [ "${verity_lines}" -lt 1 ] || [ "${erofs_lines}" -lt 1 ]; then + echo "--- last 100 lines of dmesg ---" + printf "%s\n" "$log" + exit 1 + fi + ' + [ "$status" -eq 0 ] || \ + die "dm-verity + EROFS mount evidence not found in guest dmesg: ${output}" +} + +teardown() { + # `setup` may have skipped before exporting node/pod_name; guard each step. + if [[ "${SNAPSHOTTER:-}" == "erofs" \ + && "${EROFS_SNAPSHOTTER_MODE:-}" == "integrity" ]]; then + # Debugging information + kubectl describe "pod/${pod_name}" + kubectl get "pod/${pod_name}" -o yaml + kubectl delete pod --grace-period=0 --force --ignore-not-found \ + "${pod_name:-erofs-dmverity-probe}" || true + teardown_common "${node:-}" "${node_start_time:-}" + fi +} + diff --git a/tests/integration/kubernetes/run_kubernetes_tests.sh b/tests/integration/kubernetes/run_kubernetes_tests.sh index 115c6fb949..511ca0d5b2 100755 --- a/tests/integration/kubernetes/run_kubernetes_tests.sh +++ b/tests/integration/kubernetes/run_kubernetes_tests.sh @@ -75,6 +75,7 @@ else "k8s-custom-dns.bats" \ "k8s-empty-dirs.bats" \ "k8s-env.bats" \ + "k8s-erofs-dmverity.bats" \ "k8s-exec.bats" \ "k8s-file-volume.bats" \ "k8s-hostname.bats" \ diff --git a/tests/integration/kubernetes/runtimeclass_workloads/pod-erofs-dmverity-probe.yaml b/tests/integration/kubernetes/runtimeclass_workloads/pod-erofs-dmverity-probe.yaml new file mode 100644 index 0000000000..697fb9c98e --- /dev/null +++ b/tests/integration/kubernetes/runtimeclass_workloads/pod-erofs-dmverity-probe.yaml @@ -0,0 +1,19 @@ +# +# Copyright (c) 2026 Ant Group +# +# SPDX-License-Identifier: Apache-2.0 +# +# Probe pod used by k8s-erofs-dmverity.bats. +# + +apiVersion: v1 +kind: Pod +metadata: + name: erofs-dmverity-probe +spec: + runtimeClassName: kata + restartPolicy: Never + containers: + - image: registry.k8s.io/e2e-test-images/agnhost:2.21 + name: probe + command: ["sleep", "3600"]