mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-10 12:22:36 +00:00
Merge pull request #10009 from Xynnn007/feat-cosign
Merge to main: supporting pull cosign signed images
This commit is contained in:
commit
fc5a631791
@ -159,7 +159,7 @@ vendor:
|
|||||||
|
|
||||||
#TARGET test: run cargo tests
|
#TARGET test: run cargo tests
|
||||||
test: $(GENERATED_FILES)
|
test: $(GENERATED_FILES)
|
||||||
@RUST_LIB_BACKTRACE=0 cargo test --all --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture
|
@RUST_LIB_BACKTRACE=0 RUST_BACKTRACE=1 cargo test --all --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture
|
||||||
|
|
||||||
##TARGET check: run test
|
##TARGET check: run test
|
||||||
check: $(GENERATED_FILES) standard_rust_check
|
check: $(GENERATED_FILES) standard_rust_check
|
||||||
|
@ -131,6 +131,8 @@ The kata agent has the ability to configure agent options in guest kernel comman
|
|||||||
| `agent.cdh_api_timeout` | Confidential Data Hub (CDH) API timeout | Allow to configure CDH API timeout(seconds) | integer | `50` |
|
| `agent.cdh_api_timeout` | Confidential Data Hub (CDH) API timeout | Allow to configure CDH API timeout(seconds) | integer | `50` |
|
||||||
| `agent.https_proxy` | HTTPS proxy | Allow to configure `https_proxy` in the guest | string | `""` |
|
| `agent.https_proxy` | HTTPS proxy | Allow to configure `https_proxy` in the guest | string | `""` |
|
||||||
| `agent.image_registry_auth` | Image registry credential URI | The URI to where image-rs can find the credentials for pulling images from private registries e.g. `file:///root/.docker/config.json` to read from a file in the guest image, or `kbs:///default/credentials/test` to get the file from the KBS| string | `""` |
|
| `agent.image_registry_auth` | Image registry credential URI | The URI to where image-rs can find the credentials for pulling images from private registries e.g. `file:///root/.docker/config.json` to read from a file in the guest image, or `kbs:///default/credentials/test` to get the file from the KBS| string | `""` |
|
||||||
|
| `agent.enable_signature_verification` | Image security policy flag | Whether enable image security policy enforcement. If `true`, the resource indexed by URI `agent.image_policy_file` will be got to work as image pulling policy. | string | `""` |
|
||||||
|
| `agent.image_policy_file` | Image security policy URI | The URI to where image-rs Typical policy URIs are like `file:///etc/image.json` to read from a file in the guest image, or `kbs:///default/security-policy/test` to get the file from the KBS| string | `""` |
|
||||||
| `agent.log` | Log level | Allow the agent log level to be changed (produces more or less output) | string | `"info"` |
|
| `agent.log` | Log level | Allow the agent log level to be changed (produces more or less output) | string | `"info"` |
|
||||||
| `agent.log_vport` | Log port | Allow to specify the `vsock` port to read logs | integer | `0` |
|
| `agent.log_vport` | Log port | Allow to specify the `vsock` port to read logs | integer | `0` |
|
||||||
| `agent.no_proxy` | NO proxy | Allow to configure `no_proxy` in the guest | string | `""` |
|
| `agent.no_proxy` | NO proxy | Allow to configure `no_proxy` in the guest | string | `""` |
|
||||||
|
@ -34,6 +34,12 @@ const GUEST_COMPONENTS_PROCS_OPTION: &str = "agent.guest_components_procs";
|
|||||||
const IMAGE_REGISTRY_AUTH_OPTION: &str = "agent.image_registry_auth";
|
const IMAGE_REGISTRY_AUTH_OPTION: &str = "agent.image_registry_auth";
|
||||||
const SECURE_STORAGE_INTEGRITY_OPTION: &str = "agent.secure_storage_integrity";
|
const SECURE_STORAGE_INTEGRITY_OPTION: &str = "agent.secure_storage_integrity";
|
||||||
|
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
const ENABLE_SIGNATURE_VERIFICATION: &str = "agent.enable_signature_verification";
|
||||||
|
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
const IMAGE_POLICY_FILE: &str = "agent.image_policy_file";
|
||||||
|
|
||||||
// Configure the proxy settings for HTTPS requests in the guest,
|
// Configure the proxy settings for HTTPS requests in the guest,
|
||||||
// to solve the problem of not being able to access the specified image in some cases.
|
// to solve the problem of not being able to access the specified image in some cases.
|
||||||
const HTTPS_PROXY: &str = "agent.https_proxy";
|
const HTTPS_PROXY: &str = "agent.https_proxy";
|
||||||
@ -115,6 +121,10 @@ pub struct AgentConfig {
|
|||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
pub image_registry_auth: String,
|
pub image_registry_auth: String,
|
||||||
pub secure_storage_integrity: bool,
|
pub secure_storage_integrity: bool,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
pub enable_signature_verification: bool,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
pub image_policy_file: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -138,6 +148,10 @@ pub struct AgentConfigBuilder {
|
|||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
pub image_registry_auth: Option<String>,
|
pub image_registry_auth: Option<String>,
|
||||||
pub secure_storage_integrity: Option<bool>,
|
pub secure_storage_integrity: Option<bool>,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
pub enable_signature_verification: Option<bool>,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
pub image_policy_file: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! config_override {
|
macro_rules! config_override {
|
||||||
@ -207,6 +221,10 @@ impl Default for AgentConfig {
|
|||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
image_registry_auth: String::from(""),
|
image_registry_auth: String::from(""),
|
||||||
secure_storage_integrity: false,
|
secure_storage_integrity: false,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
enable_signature_verification: false,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
image_policy_file: String::from(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,8 +264,17 @@ impl FromStr for AgentConfig {
|
|||||||
);
|
);
|
||||||
config_override!(agent_config_builder, agent_config, guest_components_procs);
|
config_override!(agent_config_builder, agent_config, guest_components_procs);
|
||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
|
{
|
||||||
config_override!(agent_config_builder, agent_config, image_registry_auth);
|
config_override!(agent_config_builder, agent_config, image_registry_auth);
|
||||||
|
config_override!(
|
||||||
|
agent_config_builder,
|
||||||
|
agent_config,
|
||||||
|
enable_signature_verification
|
||||||
|
);
|
||||||
|
config_override!(agent_config_builder, agent_config, image_policy_file);
|
||||||
|
}
|
||||||
config_override!(agent_config_builder, agent_config, secure_storage_integrity);
|
config_override!(agent_config_builder, agent_config, secure_storage_integrity);
|
||||||
|
|
||||||
Ok(agent_config)
|
Ok(agent_config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,12 +399,26 @@ impl AgentConfig {
|
|||||||
get_guest_components_procs_value
|
get_guest_components_procs_value
|
||||||
);
|
);
|
||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
|
{
|
||||||
parse_cmdline_param!(
|
parse_cmdline_param!(
|
||||||
param,
|
param,
|
||||||
IMAGE_REGISTRY_AUTH_OPTION,
|
IMAGE_REGISTRY_AUTH_OPTION,
|
||||||
config.image_registry_auth,
|
config.image_registry_auth,
|
||||||
get_string_value
|
get_string_value
|
||||||
);
|
);
|
||||||
|
parse_cmdline_param!(
|
||||||
|
param,
|
||||||
|
ENABLE_SIGNATURE_VERIFICATION,
|
||||||
|
config.enable_signature_verification,
|
||||||
|
get_bool_value
|
||||||
|
);
|
||||||
|
parse_cmdline_param!(
|
||||||
|
param,
|
||||||
|
IMAGE_POLICY_FILE,
|
||||||
|
config.image_policy_file,
|
||||||
|
get_string_value
|
||||||
|
);
|
||||||
|
}
|
||||||
parse_cmdline_param!(
|
parse_cmdline_param!(
|
||||||
param,
|
param,
|
||||||
SECURE_STORAGE_INTEGRITY_OPTION,
|
SECURE_STORAGE_INTEGRITY_OPTION,
|
||||||
@ -585,6 +626,11 @@ mod tests {
|
|||||||
assert!(!config.dev_mode);
|
assert!(!config.dev_mode);
|
||||||
assert_eq!(config.log_level, DEFAULT_LOG_LEVEL);
|
assert_eq!(config.log_level, DEFAULT_LOG_LEVEL);
|
||||||
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
|
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
{
|
||||||
|
assert!(!config.enable_signature_verification);
|
||||||
|
assert_eq!(config.image_policy_file, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -612,6 +658,10 @@ mod tests {
|
|||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
image_registry_auth: &'a str,
|
image_registry_auth: &'a str,
|
||||||
secure_storage_integrity: bool,
|
secure_storage_integrity: bool,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
enable_signature_verification: bool,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
image_policy_file: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TestData<'_> {
|
impl Default for TestData<'_> {
|
||||||
@ -634,6 +684,10 @@ mod tests {
|
|||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
image_registry_auth: "",
|
image_registry_auth: "",
|
||||||
secure_storage_integrity: false,
|
secure_storage_integrity: false,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
enable_signature_verification: false,
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
image_policy_file: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1102,6 +1156,24 @@ mod tests {
|
|||||||
secure_storage_integrity: false,
|
secure_storage_integrity: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
TestData {
|
||||||
|
contents: "agent.enable_signature_verification=true",
|
||||||
|
enable_signature_verification: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
TestData {
|
||||||
|
contents: "agent.image_policy_file=kbs:///default/image-policy/test",
|
||||||
|
image_policy_file: "kbs:///default/image-policy/test",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
#[cfg(feature = "guest-pull")]
|
||||||
|
TestData {
|
||||||
|
contents: "agent.image_policy_file=file:///etc/image-policy.json",
|
||||||
|
image_policy_file: "file:///etc/image-policy.json",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let dir = tempdir().expect("failed to create tmpdir");
|
let dir = tempdir().expect("failed to create tmpdir");
|
||||||
@ -1162,13 +1234,20 @@ mod tests {
|
|||||||
msg
|
msg
|
||||||
);
|
);
|
||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
|
{
|
||||||
assert_eq!(d.image_registry_auth, config.image_registry_auth, "{}", msg);
|
assert_eq!(d.image_registry_auth, config.image_registry_auth, "{}", msg);
|
||||||
|
assert_eq!(
|
||||||
|
d.enable_signature_verification, config.enable_signature_verification,
|
||||||
|
"{}",
|
||||||
|
msg
|
||||||
|
);
|
||||||
|
assert_eq!(d.image_policy_file, config.image_policy_file, "{}", msg);
|
||||||
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
d.secure_storage_integrity, config.secure_storage_integrity,
|
d.secure_storage_integrity, config.secure_storage_integrity,
|
||||||
"{}",
|
"{}",
|
||||||
msg
|
msg
|
||||||
);
|
);
|
||||||
|
|
||||||
for v in vars_to_unset {
|
for v in vars_to_unset {
|
||||||
env::remove_var(v);
|
env::remove_var(v);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ impl ImageService {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut image_client = ImageClient::new(PathBuf::from(KATA_IMAGE_WORK_DIR));
|
let mut image_client = ImageClient::new(PathBuf::from(KATA_IMAGE_WORK_DIR));
|
||||||
#[cfg(feature = "guest-pull")]
|
#[cfg(feature = "guest-pull")]
|
||||||
|
{
|
||||||
if !AGENT_CONFIG.image_registry_auth.is_empty() {
|
if !AGENT_CONFIG.image_registry_auth.is_empty() {
|
||||||
let registry_auth = &AGENT_CONFIG.image_registry_auth;
|
let registry_auth = &AGENT_CONFIG.image_registry_auth;
|
||||||
debug!(sl(), "Set registry auth file {:?}", registry_auth);
|
debug!(sl(), "Set registry auth file {:?}", registry_auth);
|
||||||
@ -64,6 +65,19 @@ impl ImageService {
|
|||||||
image_client.config.auth = true;
|
image_client.config.auth = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let enable_signature_verification = &AGENT_CONFIG.enable_signature_verification;
|
||||||
|
debug!(
|
||||||
|
sl(),
|
||||||
|
"Enable image signature verification: {:?}", enable_signature_verification
|
||||||
|
);
|
||||||
|
image_client.config.security_validate = *enable_signature_verification;
|
||||||
|
|
||||||
|
if !AGENT_CONFIG.image_policy_file.is_empty() {
|
||||||
|
let image_policy_file = &AGENT_CONFIG.image_policy_file;
|
||||||
|
debug!(sl(), "Use imagepolicy file {:?}", image_policy_file);
|
||||||
|
image_client.config.file_paths.policy_path = image_policy_file.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
Self { image_client }
|
Self { image_client }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
source "${BATS_TEST_DIRNAME}/tests_common.sh"
|
source "${BATS_TEST_DIRNAME}/tests_common.sh"
|
||||||
source "${BATS_TEST_DIRNAME}/../../common.bash"
|
source "${BATS_TEST_DIRNAME}/../../common.bash"
|
||||||
|
|
||||||
|
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
||||||
|
|
||||||
SUPPORTED_TEE_HYPERVISORS=("qemu-sev" "qemu-snp" "qemu-tdx" "qemu-se")
|
SUPPORTED_TEE_HYPERVISORS=("qemu-sev" "qemu-snp" "qemu-tdx" "qemu-se")
|
||||||
SUPPORTED_NON_TEE_HYPERVISORS=("qemu-coco-dev")
|
SUPPORTED_NON_TEE_HYPERVISORS=("qemu-coco-dev")
|
||||||
|
|
||||||
@ -107,3 +109,62 @@ function cleanup_loop_device(){
|
|||||||
|
|
||||||
sudo rm -f "$loop_file" >/dev/null 2>&1 || true
|
sudo rm -f "$loop_file" >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function creates pod yaml. Parameters
|
||||||
|
# - $1: image reference
|
||||||
|
# - $2: image policy file. If given, `enable_signature_verification` will be set to true
|
||||||
|
# - $3: image registry auth.
|
||||||
|
# - $4: guest components procs parameter
|
||||||
|
# - $5: guest components rest api parameter
|
||||||
|
# - $6: node
|
||||||
|
function create_coco_pod_yaml() {
|
||||||
|
image=$1
|
||||||
|
image_policy=${2:-}
|
||||||
|
image_registry_auth=${3:-}
|
||||||
|
guest_components_procs=${4:-}
|
||||||
|
guest_components_rest_api=${5:-}
|
||||||
|
node=${6:-}
|
||||||
|
|
||||||
|
local CC_KBS_ADDR
|
||||||
|
export CC_KBS_ADDR=$(kbs_k8s_svc_http_addr)
|
||||||
|
|
||||||
|
kernel_params_annotation="io.katacontainers.config.hypervisor.kernel_params"
|
||||||
|
kernel_params_value=""
|
||||||
|
|
||||||
|
if [ -n "$image_policy" ]; then
|
||||||
|
kernel_params_value+=" agent.image_policy_file=${image_policy}"
|
||||||
|
kernel_params_value+=" agent.enable_signature_verification=true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$image_registry_auth" ]; then
|
||||||
|
kernel_params_value+=" agent.image_registry_auth=${image_registry_auth}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$guest_components_procs" ]; then
|
||||||
|
kernel_params_value+=" agent.guest_components_procs=${guest_components_procs}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$guest_components_rest_api" ]; then
|
||||||
|
kernel_params_value+=" agent.guest_components_rest_api=${guest_components_rest_api}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
kernel_params_value+=" agent.aa_kbc_params=cc_kbc::${CC_KBS_ADDR}"
|
||||||
|
|
||||||
|
# Note: this is not local as we use it in the caller test
|
||||||
|
kata_pod="$(new_pod_config "$image" "kata-${KATA_HYPERVISOR}")"
|
||||||
|
set_container_command "${kata_pod}" "0" "sleep" "30"
|
||||||
|
|
||||||
|
# Set annotations
|
||||||
|
set_metadata_annotation "${kata_pod}" \
|
||||||
|
"io.containerd.cri.runtime-handler" \
|
||||||
|
"kata-${KATA_HYPERVISOR}"
|
||||||
|
set_metadata_annotation "${kata_pod}" \
|
||||||
|
"${kernel_params_annotation}" \
|
||||||
|
"${kernel_params_value}"
|
||||||
|
|
||||||
|
add_allow_all_policy_to_yaml "${kata_pod}"
|
||||||
|
|
||||||
|
if [ -n "$node" ]; then
|
||||||
|
set_node "${kata_pod}" "$node"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
load "${BATS_TEST_DIRNAME}/lib.sh"
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
|
||||||
|
|
||||||
export KBS="${KBS:-false}"
|
export KBS="${KBS:-false}"
|
||||||
export test_key="aatest"
|
export test_key="aatest"
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
load "${BATS_TEST_DIRNAME}/lib.sh"
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
|
||||||
|
|
||||||
export KBS="${KBS:-false}"
|
export KBS="${KBS:-false}"
|
||||||
|
|
||||||
@ -63,72 +62,44 @@ function setup_kbs_credentials() {
|
|||||||
kbs_set_resource "default" "credentials" "test" "${auth_json}"
|
kbs_set_resource "default" "credentials" "test" "${auth_json}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_pod_yaml_with_private_image() {
|
|
||||||
image=$1
|
|
||||||
auth_path_set=${2:-true}
|
|
||||||
|
|
||||||
# Note: this is not local as we use it in the caller test
|
|
||||||
kata_pod_with_private_image="$(new_pod_config "$image" "kata-${KATA_HYPERVISOR}")"
|
|
||||||
set_node "${kata_pod_with_private_image}" "$node"
|
|
||||||
set_container_command "${kata_pod_with_private_image}" "0" "sleep" "30"
|
|
||||||
|
|
||||||
local CC_KBS_ADDR
|
|
||||||
export CC_KBS_ADDR=$(kbs_k8s_svc_http_addr)
|
|
||||||
kernel_params_annotation="io.katacontainers.config.hypervisor.kernel_params"
|
|
||||||
kernel_params_value="agent.guest_components_rest_api=resource"
|
|
||||||
|
|
||||||
if [[ $auth_path_set == true ]]; then
|
|
||||||
kernel_params_value+=" agent.aa_kbc_params=cc_kbc::${CC_KBS_ADDR}"
|
|
||||||
kernel_params_value+=" agent.image_registry_auth=kbs:///default/credentials/test"
|
|
||||||
fi
|
|
||||||
set_metadata_annotation "${kata_pod_with_private_image}" \
|
|
||||||
"${kernel_params_annotation}" \
|
|
||||||
"${kernel_params_value}"
|
|
||||||
|
|
||||||
# Set annotation to pull image in guest
|
|
||||||
set_metadata_annotation "${kata_pod_with_private_image}" \
|
|
||||||
"io.containerd.cri.runtime-handler" \
|
|
||||||
"kata-${KATA_HYPERVISOR}"
|
|
||||||
|
|
||||||
add_allow_all_policy_to_yaml "${kata_pod_with_private_image}"
|
|
||||||
|
|
||||||
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod_with_private_image}"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test that creating a container from an authenticated image, with correct credentials works" {
|
@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}
|
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} ${AUTHENTICATED_IMAGE_PASSWORD}
|
||||||
|
|
||||||
create_pod_yaml_with_private_image "${AUTHENTICATED_IMAGE}"
|
create_coco_pod_yaml "${AUTHENTICATED_IMAGE}" "" "kbs:///default/credentials/test" "" "resource" "$node"
|
||||||
|
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_private_image}: $(cat ${kata_pod_with_private_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
k8s_create_pod "${kata_pod_with_private_image}"
|
k8s_create_pod "${kata_pod}"
|
||||||
echo "Kata pod test-e2e from authenticated image is running"
|
echo "Kata pod test-e2e from authenticated image is running"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Test that creating a container from an authenticated image, with incorrect credentials fails" {
|
@test "Test that creating a container from an authenticated image, with incorrect credentials fails" {
|
||||||
|
|
||||||
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} "junk"
|
setup_kbs_credentials "${AUTHENTICATED_IMAGE}" ${AUTHENTICATED_IMAGE_USER} "junk"
|
||||||
create_pod_yaml_with_private_image "${AUTHENTICATED_IMAGE}"
|
|
||||||
|
create_coco_pod_yaml "${AUTHENTICATED_IMAGE}" "" "kbs:///default/credentials/test" "" "resource" "$node"
|
||||||
|
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_private_image}: $(cat ${kata_pod_with_private_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
assert_pod_fail "${kata_pod_with_private_image}"
|
assert_pod_fail "${kata_pod}"
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull manifest Not authorized"
|
assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull manifest Not authorized"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Test that creating a container from an authenticated image, with no credentials fails" {
|
@test "Test that creating a container from an authenticated image, with no credentials fails" {
|
||||||
|
|
||||||
# Create pod config, but don't add agent.image_registry_auth annotation
|
# Create pod config, but don't add agent.image_registry_auth annotation
|
||||||
create_pod_yaml_with_private_image "${AUTHENTICATED_IMAGE}" false
|
create_coco_pod_yaml "${AUTHENTICATED_IMAGE}" "" "" "" "resource" "$node"
|
||||||
|
yq -i ".spec.imagePullSecrets[0].name = \"cococred\"" "${kata_pod}"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_private_image}: $(cat ${kata_pod_with_private_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
assert_pod_fail "${kata_pod_with_private_image}"
|
assert_pod_fail "${kata_pod}"
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull manifest Not authorized"
|
assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull manifest Not authorized"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
load "${BATS_TEST_DIRNAME}/lib.sh"
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
|
||||||
|
|
||||||
export KBS="${KBS:-false}"
|
export KBS="${KBS:-false}"
|
||||||
|
|
||||||
@ -39,32 +38,6 @@ function setup_kbs_decryption_key() {
|
|||||||
kbs_set_resource_base64 "default" "key" "${decryption_key_id}" "${decryption_key}"
|
kbs_set_resource_base64 "default" "key" "${decryption_key_id}" "${decryption_key}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_pod_yaml_with_encrypted_image() {
|
|
||||||
image=$1
|
|
||||||
|
|
||||||
# Note: this is not local as we use it in the caller test
|
|
||||||
kata_pod_with_encrypted_image="$(new_pod_config "$image" "kata-${KATA_HYPERVISOR}")"
|
|
||||||
set_node "${kata_pod_with_encrypted_image}" "$node"
|
|
||||||
set_container_command "${kata_pod_with_encrypted_image}" "0" "sleep" "30"
|
|
||||||
|
|
||||||
local CC_KBS_ADDR
|
|
||||||
export CC_KBS_ADDR=$(kbs_k8s_svc_http_addr)
|
|
||||||
kernel_params_annotation="io.katacontainers.config.hypervisor.kernel_params"
|
|
||||||
kernel_params_value+=" agent.guest_components_procs=confidential-data-hub"
|
|
||||||
kernel_params_value+=" agent.aa_kbc_params=cc_kbc::${CC_KBS_ADDR}"
|
|
||||||
|
|
||||||
set_metadata_annotation "${kata_pod_with_encrypted_image}" \
|
|
||||||
"${kernel_params_annotation}" \
|
|
||||||
"${kernel_params_value}"
|
|
||||||
|
|
||||||
# Set annotation to pull image in guest
|
|
||||||
set_metadata_annotation "${kata_pod_with_encrypted_image}" \
|
|
||||||
"io.containerd.cri.runtime-handler" \
|
|
||||||
"kata-${KATA_HYPERVISOR}"
|
|
||||||
|
|
||||||
add_allow_all_policy_to_yaml "${kata_pod_with_encrypted_image}"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test that creating a container from an encrypted image, with no decryption key fails" {
|
@test "Test that creating a container from an encrypted image, with no decryption key fails" {
|
||||||
|
|
||||||
# TODO - there is now delete KBS resource to ensure there is no key, so we need to keep
|
# TODO - there is now delete KBS resource to ensure there is no key, so we need to keep
|
||||||
@ -73,12 +46,12 @@ function create_pod_yaml_with_encrypted_image() {
|
|||||||
# policy, so for TEE tests we'd stay remaining with reject all, which could cause other
|
# policy, so for TEE tests we'd stay remaining with reject all, which could cause other
|
||||||
# subsequent tests to fail
|
# subsequent tests to fail
|
||||||
|
|
||||||
create_pod_yaml_with_encrypted_image "${ENCRYPTED_IMAGE}"
|
create_coco_pod_yaml "${ENCRYPTED_IMAGE}" "" "" "confidential-data-hub" "" "$node"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_encrypted_image}: $(cat ${kata_pod_with_encrypted_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
assert_pod_fail "${kata_pod_with_encrypted_image}"
|
assert_pod_fail "${kata_pod}"
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" 'failed to get decrypt key'
|
assert_logs_contain "${node}" kata "${node_start_time}" 'failed to get decrypt key'
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" 'no suitable key found for decrypting layer key'
|
assert_logs_contain "${node}" kata "${node_start_time}" 'no suitable key found for decrypting layer key'
|
||||||
}
|
}
|
||||||
@ -88,12 +61,12 @@ function create_pod_yaml_with_encrypted_image() {
|
|||||||
|
|
||||||
setup_kbs_decryption_key "${DECRYPTION_KEY}" "${DECRYPTION_KEY_ID}"
|
setup_kbs_decryption_key "${DECRYPTION_KEY}" "${DECRYPTION_KEY_ID}"
|
||||||
|
|
||||||
create_pod_yaml_with_encrypted_image "${ENCRYPTED_IMAGE}"
|
create_coco_pod_yaml "${ENCRYPTED_IMAGE}" "" "" "confidential-data-hub" "" "$node"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_encrypted_image}: $(cat ${kata_pod_with_encrypted_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
k8s_create_pod "${kata_pod_with_encrypted_image}"
|
k8s_create_pod "${kata_pod}"
|
||||||
echo "Kata pod test-e2e from encrypted image is running"
|
echo "Kata pod test-e2e from encrypted image is running"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,12 +74,12 @@ function create_pod_yaml_with_encrypted_image() {
|
|||||||
|
|
||||||
setup_kbs_decryption_key "anVua19rZXk=" "${DECRYPTION_KEY_ID}"
|
setup_kbs_decryption_key "anVua19rZXk=" "${DECRYPTION_KEY_ID}"
|
||||||
|
|
||||||
create_pod_yaml_with_encrypted_image "${ENCRYPTED_IMAGE}"
|
create_coco_pod_yaml "${ENCRYPTED_IMAGE}" "" "" "confidential-data-hub" "" "$node"
|
||||||
|
|
||||||
# For debug sake
|
# For debug sake
|
||||||
echo "Pod ${kata_pod_with_encrypted_image}: $(cat ${kata_pod_with_encrypted_image})"
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
assert_pod_fail "${kata_pod_with_encrypted_image}"
|
assert_pod_fail "${kata_pod}"
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" 'failed to get decrypt key'
|
assert_logs_contain "${node}" kata "${node_start_time}" 'failed to get decrypt key'
|
||||||
assert_logs_contain "${node}" kata "${node_start_time}" 'no suitable key found for decrypting layer key'
|
assert_logs_contain "${node}" kata "${node_start_time}" 'no suitable key found for decrypting layer key'
|
||||||
}
|
}
|
||||||
|
156
tests/integration/kubernetes/k8s-guest-pull-image-signature.bats
Normal file
156
tests/integration/kubernetes/k8s-guest-pull-image-signature.bats
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
# Copyright (c) 2024 IBM Corporation
|
||||||
|
# Copyright (c) 2024 Alibaba Corporation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
|
|
||||||
|
export KBS="${KBS:-false}"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
tag_suffix=""
|
||||||
|
if [ "$(uname -m)" != "x86_64" ]; then
|
||||||
|
tag_suffix="-$(uname -m)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
setup_common
|
||||||
|
UNSIGNED_UNPROTECTED_REGISTRY_IMAGE="quay.io/prometheus/busybox:latest"
|
||||||
|
UNSIGNED_PROTECTED_REGISTRY_IMAGE="ghcr.io/confidential-containers/test-container-image-rs:unsigned${tag_suffix}"
|
||||||
|
COSIGN_SIGNED_PROTECTED_REGISTRY_IMAGE="ghcr.io/confidential-containers/test-container-image-rs:cosign-signed${tag_suffix}"
|
||||||
|
COSIGNED_SIGNED_PROTECTED_REGISTRY_WRONG_KEY_IMAGE="ghcr.io/confidential-containers/test-container-image-rs:cosign-signed-key2${tag_suffix}"
|
||||||
|
SECURITY_POLICY_KBS_URI="kbs:///default/security-policy/test"
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_kbs_image_policy() {
|
||||||
|
if [ "${KBS}" = "false" ]; then
|
||||||
|
skip "Test skipped as KBS not setup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
default_policy="${1:-insecureAcceptAnything}"
|
||||||
|
policy_json=$(cat << EOF
|
||||||
|
{
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"type": "${default_policy}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transports": {
|
||||||
|
"docker": {
|
||||||
|
"ghcr.io/confidential-containers/test-container-image-rs": [
|
||||||
|
{
|
||||||
|
"type": "sigstoreSigned",
|
||||||
|
"keyPath": "kbs:///default/cosign-public-key/test"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quay.io/prometheus": [
|
||||||
|
{
|
||||||
|
"type": "insecureAcceptAnything"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# This public key is corresponding to a private key that was generated to test signed images in image-rs CI.
|
||||||
|
# TODO: Update the CI to generate a signed image together with verification. See issue #9360
|
||||||
|
public_key=$(curl -sSL "https://raw.githubusercontent.com/confidential-containers/guest-components/075b9a9ee77227d9d92b6f3649ef69de5e72d204/image-rs/test_data/signature/cosign/cosign1.pub")
|
||||||
|
|
||||||
|
if ! is_confidential_hardware; then
|
||||||
|
kbs_set_allow_all_resources
|
||||||
|
fi
|
||||||
|
|
||||||
|
kbs_set_resource "default" "security-policy" "test" "${policy_json}"
|
||||||
|
kbs_set_resource "default" "cosign-public-key" "test" "${public_key}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@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"
|
||||||
|
|
||||||
|
create_coco_pod_yaml "${UNSIGNED_UNPROTECTED_REGISTRY_IMAGE}" "${SECURITY_POLICY_KBS_URI}" "" "" "resource" "$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" {
|
||||||
|
# We want to leave the default policy to be insecureAcceptAnything to rule out false negatives
|
||||||
|
setup_kbs_image_policy
|
||||||
|
|
||||||
|
create_coco_pod_yaml "${UNSIGNED_PROTECTED_REGISTRY_IMAGE}" "${SECURITY_POLICY_KBS_URI}" "" "" "resource" "$node"
|
||||||
|
|
||||||
|
# For debug sake
|
||||||
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
|
assert_pod_fail "${kata_pod}"
|
||||||
|
assert_logs_contain "${node}" kata "${node_start_time}" "Security validate failed: Validate image failed: Cannot pull manifest"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Create a pod from a signed image, on a 'restricted registry' is successful" {
|
||||||
|
# We want to set the default policy to be reject to rule out false positives
|
||||||
|
setup_kbs_image_policy "reject"
|
||||||
|
|
||||||
|
create_coco_pod_yaml "${COSIGN_SIGNED_PROTECTED_REGISTRY_IMAGE}" "${SECURITY_POLICY_KBS_URI}" "" "" "resource" "$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" {
|
||||||
|
# We want to leave the default policy to be insecureAcceptAnything to rule out false negatives
|
||||||
|
setup_kbs_image_policy
|
||||||
|
|
||||||
|
create_coco_pod_yaml "${COSIGNED_SIGNED_PROTECTED_REGISTRY_WRONG_KEY_IMAGE}" "${SECURITY_POLICY_KBS_URI}" "" "" "resource" "$node"
|
||||||
|
|
||||||
|
# For debug sake
|
||||||
|
echo "Pod ${kata_pod}: $(cat ${kata_pod})"
|
||||||
|
|
||||||
|
assert_pod_fail "${kata_pod}"
|
||||||
|
assert_logs_contain "${node}" kata "${node_start_time}" "Security validate failed: Validate image failed: \[PublicKeyVerifier"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Create a pod from an unsigned image, on a 'restricted registry' works if policy files isn't set" {
|
||||||
|
# We want to set the default policy to be reject to rule out false positives
|
||||||
|
setup_kbs_image_policy "reject"
|
||||||
|
|
||||||
|
create_coco_pod_yaml "${UNSIGNED_PROTECTED_REGISTRY_IMAGE}" "" "" "" "resource" "$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}."
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ "${SNAPSHOTTER:-}" = "nydus" ] || skip "None snapshotter was found but this test requires one"
|
||||||
|
|
||||||
|
kubectl describe pods
|
||||||
|
k8s_delete_all_pods_if_any_exists || true
|
||||||
|
|
||||||
|
if [[ -n "${node_start_time:-}" && -z "$BATS_TEST_COMPLETED" ]]; then
|
||||||
|
echo "DEBUG: system logs of node '$node' since test start time ($node_start_time)"
|
||||||
|
print_node_journal "$node" "kata" --since "$node_start_time" || true
|
||||||
|
fi
|
||||||
|
}
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
load "${BATS_TEST_DIRNAME}/lib.sh"
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
if ! is_confidential_runtime_class; then
|
if ! is_confidential_runtime_class; then
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
load "${BATS_TEST_DIRNAME}/lib.sh"
|
load "${BATS_TEST_DIRNAME}/lib.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
load "${BATS_TEST_DIRNAME}/confidential_common.sh"
|
||||||
load "${BATS_TEST_DIRNAME}/confidential_kbs.sh"
|
|
||||||
|
|
||||||
export KBS="${KBS:-false}"
|
export KBS="${KBS:-false}"
|
||||||
export KATA_HYPERVISOR="${KATA_HYPERVISOR:-qemu}"
|
export KATA_HYPERVISOR="${KATA_HYPERVISOR:-qemu}"
|
||||||
|
@ -28,6 +28,7 @@ else
|
|||||||
"k8s-guest-pull-image-encrypted.bats" \
|
"k8s-guest-pull-image-encrypted.bats" \
|
||||||
"k8s-guest-pull-image.bats" \
|
"k8s-guest-pull-image.bats" \
|
||||||
"k8s-guest-pull-image-authenticated.bats" \
|
"k8s-guest-pull-image-authenticated.bats" \
|
||||||
|
"k8s-guest-pull-image-signature.bats" \
|
||||||
"k8s-confidential-attestation.bats" \
|
"k8s-confidential-attestation.bats" \
|
||||||
"k8s-confidential.bats" \
|
"k8s-confidential.bats" \
|
||||||
"k8s-sealed-secret.bats" \
|
"k8s-sealed-secret.bats" \
|
||||||
|
@ -230,8 +230,8 @@ delete_tmp_policy_settings_dir() {
|
|||||||
auto_generate_policy() {
|
auto_generate_policy() {
|
||||||
declare -r settings_dir="$1"
|
declare -r settings_dir="$1"
|
||||||
declare -r yaml_file="$2"
|
declare -r yaml_file="$2"
|
||||||
declare -r config_map_yaml_file="$3"
|
declare -r config_map_yaml_file="${3:-""}"
|
||||||
declare -r additional_flags="$4"
|
declare -r additional_flags="${4:-""}"
|
||||||
|
|
||||||
auto_generate_policy_enabled || return 0
|
auto_generate_policy_enabled || return 0
|
||||||
local genpolicy_command="RUST_LOG=info /opt/kata/bin/genpolicy -u -y ${yaml_file}"
|
local genpolicy_command="RUST_LOG=info /opt/kata/bin/genpolicy -u -y ${yaml_file}"
|
||||||
|
Loading…
Reference in New Issue
Block a user