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 <xynnn@linux.alibaba.com>
This commit is contained in:
Xynnn007 2024-07-14 19:04:43 +08:00 committed by stevenhorsman
parent 653bc3973f
commit 9606e7ac8b
3 changed files with 110 additions and 15 deletions

View File

@ -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 | `""` |

View File

@ -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);
} }

View File

@ -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 }
} }