From 9606e7ac8bcf11dedd3e0feacc96e7ac072036f9 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Sun, 14 Jul 2024 19:04:43 +0800 Subject: [PATCH] agent: Set image-rs image security policy Add two parameters for enabling cosign signature image verification. - `enable_signature_verification`: to activate signature verification - `image_policy`: URI of the image policy config Signed-off-by: Xynnn007 --- src/agent/README.md | 2 + src/agent/src/config.rs | 97 +++++++++++++++++++++++++++++++++++++---- src/agent/src/image.rs | 26 ++++++++--- 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/src/agent/README.md b/src/agent/README.md index fbe445224..430967664 100644 --- a/src/agent/README.md +++ b/src/agent/README.md @@ -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.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.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_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 | `""` | diff --git a/src/agent/src/config.rs b/src/agent/src/config.rs index 9ced9fc5a..3f721afbb 100644 --- a/src/agent/src/config.rs +++ b/src/agent/src/config.rs @@ -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 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, // to solve the problem of not being able to access the specified image in some cases. const HTTPS_PROXY: &str = "agent.https_proxy"; @@ -115,6 +121,10 @@ pub struct AgentConfig { #[cfg(feature = "guest-pull")] pub image_registry_auth: String, 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)] @@ -138,6 +148,10 @@ pub struct AgentConfigBuilder { #[cfg(feature = "guest-pull")] pub image_registry_auth: Option, pub secure_storage_integrity: Option, + #[cfg(feature = "guest-pull")] + pub enable_signature_verification: Option, + #[cfg(feature = "guest-pull")] + pub image_policy_file: Option, } macro_rules! config_override { @@ -207,6 +221,10 @@ impl Default for AgentConfig { #[cfg(feature = "guest-pull")] image_registry_auth: String::from(""), 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); #[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); + Ok(agent_config) } } @@ -372,12 +399,26 @@ impl AgentConfig { get_guest_components_procs_value ); #[cfg(feature = "guest-pull")] - parse_cmdline_param!( - param, - IMAGE_REGISTRY_AUTH_OPTION, - config.image_registry_auth, - get_string_value - ); + { + parse_cmdline_param!( + param, + IMAGE_REGISTRY_AUTH_OPTION, + config.image_registry_auth, + 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!( param, SECURE_STORAGE_INTEGRITY_OPTION, @@ -585,6 +626,11 @@ mod tests { assert!(!config.dev_mode); assert_eq!(config.log_level, DEFAULT_LOG_LEVEL); assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT); + #[cfg(feature = "guest-pull")] + { + assert!(!config.enable_signature_verification); + assert_eq!(config.image_policy_file, ""); + } } #[test] @@ -612,6 +658,10 @@ mod tests { #[cfg(feature = "guest-pull")] image_registry_auth: &'a str, 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<'_> { @@ -634,6 +684,10 @@ mod tests { #[cfg(feature = "guest-pull")] image_registry_auth: "", 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, ..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"); @@ -1162,13 +1234,20 @@ mod tests { msg ); #[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!( d.secure_storage_integrity, config.secure_storage_integrity, "{}", msg ); - for v in vars_to_unset { env::remove_var(v); } diff --git a/src/agent/src/image.rs b/src/agent/src/image.rs index 0cc0d209c..5168a24f8 100644 --- a/src/agent/src/image.rs +++ b/src/agent/src/image.rs @@ -57,13 +57,27 @@ impl ImageService { pub fn new() -> Self { let mut image_client = ImageClient::new(PathBuf::from(KATA_IMAGE_WORK_DIR)); #[cfg(feature = "guest-pull")] - if !AGENT_CONFIG.image_registry_auth.is_empty() { - let registry_auth = &AGENT_CONFIG.image_registry_auth; - debug!(sl(), "Set registry auth file {:?}", registry_auth); - image_client.config.file_paths.auth_file = registry_auth.clone(); - image_client.config.auth = true; - } + { + if !AGENT_CONFIG.image_registry_auth.is_empty() { + let registry_auth = &AGENT_CONFIG.image_registry_auth; + debug!(sl(), "Set registry auth file {:?}", registry_auth); + image_client.config.file_paths.auth_file = registry_auth.clone(); + 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 } }