Merge pull request #11891 from stevenhorsman/signature-tests-with-initdata

tests/k8s: Add initdata variants of signature verification and registry authentication tests
This commit is contained in:
Hyounggyu Choi
2025-10-22 20:27:26 +02:00
committed by GitHub
5 changed files with 230 additions and 197 deletions

View File

@@ -213,6 +213,79 @@ function create_coco_pod_yaml_with_annotations() {
fi
}
function get_initdata_with_cdh_image_section() {
CDH_IMAGE_SECTION=${1:-""}
CC_KBS_ADDRESS=$(kbs_k8s_svc_http_addr)
initdata_annotation=$(gzip -c << EOF | base64 -w0
version = "0.1.0"
algorithm = "sha256"
[data]
"aa.toml" = '''
[token_configs]
[token_configs.kbs]
url = "${CC_KBS_ADDRESS}"
'''
"cdh.toml" = '''
[kbc]
name = "cc_kbc"
url = "${CC_KBS_ADDRESS}"
${CDH_IMAGE_SECTION}
'''
"policy.rego" = '''
# Copyright (c) 2023 Microsoft Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
package agent_policy
default AddARPNeighborsRequest := true
default AddSwapRequest := true
default CloseStdinRequest := true
default CopyFileRequest := true
default CreateContainerRequest := true
default CreateSandboxRequest := true
default DestroySandboxRequest := true
default ExecProcessRequest := true
default GetMetricsRequest := true
default GetOOMEventRequest := true
default GuestDetailsRequest := true
default ListInterfacesRequest := true
default ListRoutesRequest := true
default MemHotplugByProbeRequest := true
default OnlineCPUMemRequest := true
default PauseContainerRequest := true
default PullImageRequest := true
default ReadStreamRequest := true
default RemoveContainerRequest := true
default RemoveStaleVirtiofsShareMountsRequest := true
default ReseedRandomDevRequest := true
default ResumeContainerRequest := true
default SetGuestDateTimeRequest := true
default SetPolicyRequest := true
default SignalProcessRequest := true
default StartContainerRequest := true
default StartTracingRequest := true
default StatsContainerRequest := true
default StopTracingRequest := true
default TtyWinResizeRequest := true
default UpdateContainerRequest := true
default UpdateEphemeralMountsRequest := true
default UpdateInterfaceRequest := true
default UpdateRoutesRequest := true
default WaitProcessRequest := true
default WriteStreamRequest := true
'''
EOF
)
echo "${initdata_annotation}"
}
confidential_teardown_common() {
local node="$1"
local node_start_time="$2"

View File

@@ -20,6 +20,7 @@ setup() {
AUTHENTICATED_IMAGE="${AUTHENTICATED_IMAGE:-quay.io/kata-containers/confidential-containers-auth:test}"
AUTHENTICATED_IMAGE_USER=${AUTHENTICATED_IMAGE_USER:-}
AUTHENTICATED_IMAGE_PASSWORD=${AUTHENTICATED_IMAGE_PASSWORD:-}
CREDENTIALS_KBS_URI="kbs:///default/credentials/test"
if [[ -z ${AUTHENTICATED_IMAGE_USER} || -z ${AUTHENTICATED_IMAGE_PASSWORD} ]]; then
if [[ -n ${GITHUB_ACTION:-} ]]; then
@@ -62,6 +63,17 @@ function setup_kbs_credentials() {
kbs_set_resource "default" "credentials" "test" "${auth_json}"
}
function get_initdata_with_auth_registry_config() {
image_section_with_policy=$(cat << EOF
[image]
authenticated_registry_credentials_uri = "${CREDENTIALS_KBS_URI}"
EOF
)
get_initdata_with_cdh_image_section "${image_section_with_policy}"
}
@test "Test that creating a container from an authenticated image, with correct credentials works" {
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} ${AUTHENTICATED_IMAGE_PASSWORD}
@@ -103,6 +115,56 @@ function setup_kbs_credentials() {
assert_logs_contain "${node}" kata "${node_start_time}" "Not authorized"
}
@test "Test that creating a container from an authenticated image, with correct credentials works (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} ${AUTHENTICATED_IMAGE_PASSWORD}
initdata=$(get_initdata_with_auth_registry_config)
create_coco_pod_yaml_with_annotations "${AUTHENTICATED_IMAGE}" "" "${initdata}" "${node}"
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
k8s_create_pod "${kata_pod}"
echo "Kata pod test-e2e from authenticated image is running"
}
@test "Test that creating a container from an authenticated image, with incorrect credentials fails (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} "junk"
initdata=$(get_initdata_with_auth_registry_config)
create_coco_pod_yaml_with_annotations "${AUTHENTICATED_IMAGE}" "" "${initdata}" "${node}"
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
assert_pod_fail "${kata_pod}"
assert_logs_contain "${node}" kata "${node_start_time}" "Not authorized"
}
@test "Test that creating a container from an authenticated image, with no credentials fails (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# Create pod config, but don't add image_registry_auth to initdata
initdata=$(get_initdata_with_cdh_image_section "")
create_coco_pod_yaml_with_annotations "${AUTHENTICATED_IMAGE}" "" "${initdata}" "${node}"
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
assert_pod_fail "${kata_pod}"
assert_logs_contain "${node}" kata "${node_start_time}" "Not authorized"
}
teardown() {
if ! is_confidential_runtime_class; then
skip "Test not supported for ${KATA_HYPERVISOR}."

View File

@@ -74,6 +74,17 @@ EOF
kbs_set_resource "default" "cosign-public-key" "test" "${public_key}"
}
function get_initdata_with_security_policy() {
image_section_with_policy=$(cat << EOF
[image]
image_security_policy_uri = "${SECURITY_POLICY_KBS_URI}"
EOF
)
get_initdata_with_cdh_image_section "${image_section_with_policy}"
}
@test "Create a pod from an unsigned image, on an insecureAcceptAnything registry works" {
# We want to set the default policy to be reject to rule out false positives
setup_kbs_image_policy "reject"
@@ -139,6 +150,90 @@ EOF
echo "Kata pod test-e2e from image security policy is running"
}
@test "Create a pod from an unsigned image, on an insecureAcceptAnything registry works (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# We want to set the default policy to be reject to rule out false positives
setup_kbs_image_policy "reject"
initdata=$(get_initdata_with_security_policy)
create_coco_pod_yaml_with_annotations "${UNSIGNED_UNPROTECTED_REGISTRY_IMAGE}" "" "${initdata}" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
k8s_create_pod "${kata_pod}"
echo "Kata pod test-e2e from image security policy is running"
}
@test "Create a pod from an unsigned image, on a 'restricted registry' is rejected (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# We want to leave the default policy to be insecureAcceptAnything to rule out false negatives
setup_kbs_image_policy
initdata=$(get_initdata_with_security_policy)
create_coco_pod_yaml_with_annotations "${UNSIGNED_PROTECTED_REGISTRY_IMAGE}" "" "${initdata}" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
assert_pod_fail "${kata_pod}"
assert_logs_contain "${node}" kata "${node_start_time}" "Image policy rejected: Denied by policy"
}
@test "Create a pod from a signed image, on a 'restricted registry' is successful (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# We want to set the default policy to be reject to rule out false positives
setup_kbs_image_policy "reject"
initdata=$(get_initdata_with_security_policy)
create_coco_pod_yaml_with_annotations "${COSIGN_SIGNED_PROTECTED_REGISTRY_IMAGE}" "" "${initdata}" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
k8s_create_pod "${kata_pod}"
echo "Kata pod test-e2e from image security policy is running"
}
@test "Create a pod from a signed image, on a 'restricted registry', but with the wrong key is rejected (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# We want to leave the default policy to be insecureAcceptAnything to rule out false negatives
setup_kbs_image_policy
initdata=$(get_initdata_with_security_policy)
create_coco_pod_yaml_with_annotations "${COSIGNED_SIGNED_PROTECTED_REGISTRY_WRONG_KEY_IMAGE}" "" "${initdata}" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
assert_pod_fail "${kata_pod}"
assert_logs_contain "${node}" kata "${node_start_time}" "Image policy rejected: Denied by policy"
}
@test "Create a pod from an unsigned image, on a 'restricted registry' works if policy files isn't set (with initdata)" {
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "https://github.com/kata-containers/kata-containers/issues/11945"
# We want to set the default policy to be reject to rule out false positives
setup_kbs_image_policy "reject"
create_coco_pod_yaml_with_annotations "${UNSIGNED_PROTECTED_REGISTRY_IMAGE}" "" "" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
k8s_create_pod "${kata_pod}"
echo "Kata pod test-e2e from image security policy is running"
}
teardown() {
if ! is_confidential_runtime_class; then
skip "Test not supported for ${KATA_HYPERVISOR}."

View File

@@ -1,196 +0,0 @@
#!/usr/bin/env bats
# Copyright (c) 2025 Alibaba Cloud
#
# SPDX-License-Identifier: Apache-2.0
#
# This test we will test initdata in the following logic
# 1. Enable image signature verification via kernel commandline
# 2. Set Trustee address via initdata
# 3. Pull an image from a banned registry
# 4. Check if the pulling fails with log `image security validation failed`,
# the initdata works.
#
# Note that if initdata does not work, the pod still fails to launch (hang at
# CreatingContainer status). The error information is
# `[CDH] [ERROR]: Get Resource failed` which internally means that the KBS URL
# has not been set correctly.
#
# TODO: After https://github.com/kata-containers/kata-containers/issues/9266
# is resolved, both KBS URI and policy URI can be set via initdata.
load "${BATS_TEST_DIRNAME}/lib.sh"
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
export KBS="${KBS:-false}"
export KATA_HYPERVISOR="${KATA_HYPERVISOR:-qemu}"
setup() {
if ! is_confidential_runtime_class; then
skip "Test not supported for ${KATA_HYPERVISOR}."
fi
[ "${SNAPSHOTTER:-}" = "nydus" ] || skip "None snapshotter was found but this test requires one"
setup_common || die "setup_common failed"
FAIL_TEST_IMAGE="quay.io/prometheus/busybox:latest"
SECURITY_POLICY_KBS_URI="kbs:///default/security-policy/test"
}
function setup_kbs_image_policy_for_initdata() {
if [ "${KBS}" = "false" ]; then
skip "Test skipped as KBS not setup"
fi
export CURRENT_ARCH=$(uname -m)
case "${CURRENT_ARCH}" in
"x86_64"|"s390x")
;;
*)
skip "Test skipped as only x86-64 & s390x is supported, while current platform is ${CURRENT_ARCH}"
;;
esac
case "$KATA_HYPERVISOR" in
"qemu-tdx"|"qemu-coco-dev"|"qemu-snp"|"qemu-se"|"qemu-se-runtime-rs")
;;
*)
skip "Test not supported for ${KATA_HYPERVISOR}."
;;
esac
default_policy="${1:-insecureAcceptAnything}"
policy_json=$(cat << EOF
{
"default": [
{
"type": "${default_policy}"
}
],
"transports": {
"docker": {
"quay.io/prometheus": [
{
"type": "reject"
}
]
}
}
}
EOF
)
if ! is_confidential_hardware; then
kbs_set_allow_all_resources
fi
kbs_set_resource "default" "security-policy" "test" "${policy_json}"
}
@test "Test that creating a container from an rejected image configured by initdata, fails according to policy reject" {
setup_kbs_image_policy_for_initdata
CC_KBS_ADDRESS=$(kbs_k8s_svc_http_addr)
kernel_parameter="agent.image_policy_file=${SECURITY_POLICY_KBS_URI} agent.enable_signature_verification=true"
initdata_annotation=$(gzip -c << EOF | base64 -w0
version = "0.1.0"
algorithm = "sha256"
[data]
"aa.toml" = '''
[token_configs]
[token_configs.kbs]
url = "${CC_KBS_ADDRESS}"
'''
"cdh.toml" = '''
[kbc]
name = "cc_kbc"
url = "${CC_KBS_ADDRESS}"
'''
"policy.rego" = '''
# Copyright (c) 2023 Microsoft Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
package agent_policy
default AddARPNeighborsRequest := true
default AddSwapRequest := true
default CloseStdinRequest := true
default CopyFileRequest := true
default CreateContainerRequest := true
default CreateSandboxRequest := true
default DestroySandboxRequest := true
default ExecProcessRequest := true
default GetMetricsRequest := true
default GetOOMEventRequest := true
default GuestDetailsRequest := true
default ListInterfacesRequest := true
default ListRoutesRequest := true
default MemHotplugByProbeRequest := true
default OnlineCPUMemRequest := true
default PauseContainerRequest := true
default PullImageRequest := true
default ReadStreamRequest := true
default RemoveContainerRequest := true
default RemoveStaleVirtiofsShareMountsRequest := true
default ReseedRandomDevRequest := true
default ResumeContainerRequest := true
default SetGuestDateTimeRequest := true
default SetPolicyRequest := true
default SignalProcessRequest := true
default StartContainerRequest := true
default StartTracingRequest := true
default StatsContainerRequest := true
default StopTracingRequest := true
default TtyWinResizeRequest := true
default UpdateContainerRequest := true
default UpdateEphemeralMountsRequest := true
default UpdateInterfaceRequest := true
default UpdateRoutesRequest := true
default WaitProcessRequest := true
default WriteStreamRequest := true
'''
EOF
)
create_coco_pod_yaml_with_annotations "${FAIL_TEST_IMAGE}" "${kernel_parameter}" "${initdata_annotation}" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
assert_pod_fail "${kata_pod}"
assert_logs_contain "${node}" kata "${node_start_time}" "Image policy rejected: Denied by policy"
}
@test "Test that creating a container from an rejected image not configured by initdata, fails according to CDH error" {
setup_kbs_image_policy_for_initdata
kernel_parameter="agent.image_policy_file=${SECURITY_POLICY_KBS_URI} agent.enable_signature_verification=true"
create_coco_pod_yaml_with_annotations "${FAIL_TEST_IMAGE}" "${kernel_parameter}" "" "${node}"
# For debug sake
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
if k8s_create_pod "${kata_pod}" ; then
echo "Expected failure, but pod ${kata_pod} launched successfully."
return 1
fi
assert_logs_contain "${node}" kata "${node_start_time}" "\[CDH\] \[ERROR\]: Image Client error: Initialize resource provider failed: Get resource failed"
}
teardown() {
if ! is_confidential_runtime_class; then
skip "Test not supported for ${KATA_HYPERVISOR}."
fi
[ "${SNAPSHOTTER:-}" = "nydus" ] || skip "None snapshotter was found but this test requires one"
teardown_common "${node}" "${node_start_time:-}"
}

View File

@@ -38,7 +38,6 @@ else
"k8s-guest-pull-image-encrypted.bats" \
"k8s-guest-pull-image-authenticated.bats" \
"k8s-guest-pull-image-signature.bats" \
"k8s-initdata.bats" \
"k8s-confidential-attestation.bats" \
)