diff --git a/src/agent/README.md b/src/agent/README.md index f6f9047449..f8bf63255f 100644 --- a/src/agent/README.md +++ b/src/agent/README.md @@ -129,6 +129,7 @@ The kata agent has the ability to configure agent options in guest kernel comman | `agent.guest_components_rest_api` | `api-server-rest` configuration | Select the features that the API Server Rest attestation component will run with. Valid values are `all`, `attestation`, `resource` | string | `resource` | | `agent.guest_components_procs` | guest-components processes | Attestation-related processes that should be spawned as children of the guest. Valid values are `none`, `attestation-agent`, `confidential-data-hub` (implies `attestation-agent`), `api-server-rest` (implies `attestation-agent` and `confidential-data-hub`) | string | `api-server-rest` | | `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.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 3d41aa5719..00787f3d9a 100644 --- a/src/agent/src/config.rs +++ b/src/agent/src/config.rs @@ -29,6 +29,8 @@ const UNIFIED_CGROUP_HIERARCHY_OPTION: &str = "systemd.unified_cgroup_hierarchy" const CONFIG_FILE: &str = "agent.config_file"; const GUEST_COMPONENTS_REST_API_OPTION: &str = "agent.guest_components_rest_api"; const GUEST_COMPONENTS_PROCS_OPTION: &str = "agent.guest_components_procs"; +#[cfg(feature = "guest-pull")] +const IMAGE_REGISTRY_AUTH_OPTION: &str = "agent.image_registry_auth"; // 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. @@ -106,6 +108,8 @@ pub struct AgentConfig { pub no_proxy: String, pub guest_components_rest_api: GuestComponentsFeatures, pub guest_components_procs: GuestComponentsProcs, + #[cfg(feature = "guest-pull")] + pub image_registry_auth: String, } #[derive(Debug, Deserialize)] @@ -125,6 +129,8 @@ pub struct AgentConfigBuilder { pub no_proxy: Option, pub guest_components_rest_api: Option, pub guest_components_procs: Option, + #[cfg(feature = "guest-pull")] + pub image_registry_auth: Option, } macro_rules! config_override { @@ -190,6 +196,8 @@ impl Default for AgentConfig { no_proxy: String::from(""), guest_components_rest_api: GuestComponentsFeatures::default(), guest_components_procs: GuestComponentsProcs::default(), + #[cfg(feature = "guest-pull")] + image_registry_auth: String::from(""), } } } @@ -227,6 +235,8 @@ impl FromStr for AgentConfig { guest_components_rest_api ); config_override!(agent_config_builder, agent_config, guest_components_procs); + #[cfg(feature = "guest-pull")] + config_override!(agent_config_builder, agent_config, image_registry_auth); Ok(agent_config) } @@ -316,7 +326,6 @@ impl AgentConfig { get_vsock_port, |port| port > 0 ); - parse_cmdline_param!( param, CONTAINER_PIPE_SIZE_OPTION, @@ -343,6 +352,13 @@ impl AgentConfig { config.guest_components_procs, get_guest_components_procs_value ); + #[cfg(feature = "guest-pull")] + parse_cmdline_param!( + param, + IMAGE_REGISTRY_AUTH_OPTION, + config.image_registry_auth, + get_string_value + ); } config.override_config_from_envs(); @@ -505,10 +521,8 @@ fn get_url_value(param: &str) -> Result { fn get_guest_components_features_value(param: &str) -> Result { let fields: Vec<&str> = param.split('=').collect(); ensure!(fields.len() >= 2, ERR_INVALID_GET_VALUE_PARAM); - // We need name (but the value can be blank) ensure!(!fields[0].is_empty(), ERR_INVALID_GET_VALUE_NO_NAME); - let value = fields[1..].join("="); GuestComponentsFeatures::from_str(&value) .map_err(|_| anyhow!(ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE)) @@ -570,6 +584,8 @@ mod tests { no_proxy: &'a str, guest_components_rest_api: GuestComponentsFeatures, guest_components_procs: GuestComponentsProcs, + #[cfg(feature = "guest-pull")] + image_registry_auth: &'a str, } impl Default for TestData<'_> { @@ -589,6 +605,8 @@ mod tests { no_proxy: "", guest_components_rest_api: GuestComponentsFeatures::default(), guest_components_procs: GuestComponentsProcs::default(), + #[cfg(feature = "guest-pull")] + image_registry_auth: "", } } } @@ -1020,6 +1038,18 @@ mod tests { guest_components_procs: GuestComponentsProcs::None, ..Default::default() }, + #[cfg(feature = "guest-pull")] + TestData { + contents: "agent.image_registry_auth=file:///root/.docker/config.json", + image_registry_auth: "file:///root/.docker/config.json", + ..Default::default() + }, + #[cfg(feature = "guest-pull")] + TestData { + contents: "agent.image_registry_auth=kbs:///default/credentials/test", + image_registry_auth: "kbs:///default/credentials/test", + ..Default::default() + }, ]; let dir = tempdir().expect("failed to create tmpdir"); @@ -1079,6 +1109,8 @@ mod tests { "{}", msg ); + #[cfg(feature = "guest-pull")] + assert_eq!(d.image_registry_auth, config.image_registry_auth, "{}", msg); for v in vars_to_unset { env::remove_var(v);