From 997a1f35ab68ad8cc2b24e8e20ea63f7de82acf9 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 09:16:04 +0800 Subject: [PATCH 01/17] agent: add PullImage to CDH proto file CDH provides the image pull api. This commit adds the declaration of the API in the CDH proto file. This will be used in following commits. Signed-off-by: Xynnn007 --- .../protos/confidential_data_hub.proto | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libs/protocols/protos/confidential_data_hub.proto b/src/libs/protocols/protos/confidential_data_hub.proto index f639c94c98..e3d6ff00c6 100644 --- a/src/libs/protocols/protos/confidential_data_hub.proto +++ b/src/libs/protocols/protos/confidential_data_hub.proto @@ -28,6 +28,21 @@ message SecureMountResponse { string mount_path = 1; } +message ImagePullRequest { + // - `image_url`: The reference of the image to pull + string image_url = 1; + + // - `bundle_path`: The path to store the OCI bundle. This path + // should be created by client, and initially empty. After the RPC is + // called, a mounted `rootfs` directory under the this path. Note + // that this path is CDH's root filesystem, not the caller's root filesystem. + // However, usually the caller (kata-agent) and the server (CDH) runs on the same + // root, so it's safe to use an absolute path of kata-agent. + string bundle_path = 2; +} + +message ImagePullResponse {} + service SealedSecretService { rpc UnsealSecret(UnsealSecretInput) returns (UnsealSecretOutput) {}; } @@ -46,4 +61,10 @@ message GetResourceResponse { service GetResourceService { rpc GetResource(GetResourceRequest) returns (GetResourceResponse) {}; +} + +// ImagePullService is used to pull images from a remote registry +// and mount the resulting root filesystems. +service ImagePullService { + rpc PullImage(ImagePullRequest) returns (ImagePullResponse) {}; } \ No newline at end of file From 5067aafd568501bb3cfb9c4306fa764617ba7725 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 09:37:01 +0800 Subject: [PATCH 02/17] agent: move cdh.rs and image.rs to a separate module confidential_data_hub This is a little refactoring commit that moves the mod `cdh.rs` and `image.rs` to a directory module `confidential_data_hub`. This is because the image pull ability will be moved into confidential data hub, thus it is better to handle image pull things in the confidential data hub submodule. Also, this commit does some changes upon the original code. It gets rid of a static variable for CDH timeout config and directly use the global config variable's member. Also, this changes the `is_cdh_client_initialized` function to sync version as it does not need to be async. Signed-off-by: Xynnn007 --- .../src/{ => confidential_data_hub}/image.rs | 0 .../{cdh.rs => confidential_data_hub/mod.rs} | 23 +++++++----- src/agent/src/device/vfio_device_handler.rs | 2 +- src/agent/src/main.rs | 9 ++--- src/agent/src/rpc.rs | 35 ++++++++++--------- 5 files changed, 37 insertions(+), 32 deletions(-) rename src/agent/src/{ => confidential_data_hub}/image.rs (100%) rename src/agent/src/{cdh.rs => confidential_data_hub/mod.rs} (95%) diff --git a/src/agent/src/image.rs b/src/agent/src/confidential_data_hub/image.rs similarity index 100% rename from src/agent/src/image.rs rename to src/agent/src/confidential_data_hub/image.rs diff --git a/src/agent/src/cdh.rs b/src/agent/src/confidential_data_hub/mod.rs similarity index 95% rename from src/agent/src/cdh.rs rename to src/agent/src/confidential_data_hub/mod.rs index d34ad20388..36468e9779 100644 --- a/src/agent/src/cdh.rs +++ b/src/agent/src/confidential_data_hub/mod.rs @@ -23,11 +23,7 @@ use std::os::unix::fs::symlink; use std::path::Path; use tokio::sync::OnceCell; -// Nanoseconds -lazy_static! { - static ref CDH_API_TIMEOUT: i64 = AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64; - pub static ref CDH_CLIENT: OnceCell = OnceCell::new(); -} +pub static CDH_CLIENT: OnceCell = OnceCell::const_new(); const SEALED_SECRET_PREFIX: &str = "sealed."; @@ -69,7 +65,10 @@ impl CDHClient { let unsealed_secret = self .sealed_secret_client - .unseal_secret(ttrpc::context::with_timeout(*CDH_API_TIMEOUT), &input) + .unseal_secret( + ttrpc::context::with_timeout(AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64), + &input, + ) .await?; Ok(unsealed_secret.plaintext) } @@ -90,7 +89,10 @@ impl CDHClient { ..Default::default() }; self.secure_mount_client - .secure_mount(ttrpc::context::with_timeout(*CDH_API_TIMEOUT), &req) + .secure_mount( + ttrpc::context::with_timeout(AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64), + &req, + ) .await?; Ok(()) } @@ -102,7 +104,10 @@ impl CDHClient { }; let res = self .get_resource_client - .get_resource(ttrpc::context::with_timeout(*CDH_API_TIMEOUT), &req) + .get_resource( + ttrpc::context::with_timeout(AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64), + &req, + ) .await?; Ok(res.Resource) } @@ -118,7 +123,7 @@ pub async fn init_cdh_client(cdh_socket_uri: &str) -> Result<()> { } /// Check if the CDH client is initialized -pub async fn is_cdh_client_initialized() -> bool { +pub fn is_cdh_client_initialized() -> bool { CDH_CLIENT.get().is_some() // Returns true if CDH_CLIENT is initialized, false otherwise } diff --git a/src/agent/src/device/vfio_device_handler.rs b/src/agent/src/device/vfio_device_handler.rs index e0fd4d00da..ec98666883 100644 --- a/src/agent/src/device/vfio_device_handler.rs +++ b/src/agent/src/device/vfio_device_handler.rs @@ -29,7 +29,7 @@ use tracing::instrument; cfg_if! { if #[cfg(target_arch = "s390x")] { use crate::ap; - use crate::cdh::get_cdh_resource; + use crate::confidential_data_hub::get_cdh_resource; use std::convert::TryFrom; use pv_core::ap::{ Apqn, diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index cc9fa53ad5..081f14e73c 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -38,7 +38,7 @@ use std::process::exit; use std::sync::Arc; use tracing::{instrument, span}; -mod cdh; +mod confidential_data_hub; mod config; mod console; mod device; @@ -79,9 +79,6 @@ use tokio::{ task::JoinHandle, }; -#[cfg(feature = "guest-pull")] -mod image; - mod rpc; mod tracer; @@ -395,7 +392,7 @@ async fn start_sandbox( } #[cfg(feature = "guest-pull")] - image::set_proxy_env_vars().await; + confidential_data_hub::image::set_proxy_env_vars().await; #[cfg(feature = "agent-policy")] if let Err(e) = initialize_policy().await { @@ -580,7 +577,7 @@ async fn init_attestation_components( match tokio::fs::metadata(CDH_SOCKET).await { Ok(md) => { if md.file_type().is_socket() { - cdh::init_cdh_client(CDH_SOCKET_URI).await?; + confidential_data_hub::init_cdh_client(CDH_SOCKET_URI).await?; fs::write(OCICRYPT_CONFIG_PATH, OCICRYPT_CONFIG.as_bytes())?; env::set_var("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH); } else { diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 3a1a4bd70c..278cc947ad 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -57,7 +57,8 @@ use rustjail::process::ProcessOperations; #[cfg(target_arch = "s390x")] use crate::ccw; -use crate::cdh; +#[cfg(feature = "guest-pull")] +use crate::confidential_data_hub::image::KATA_IMAGE_WORK_DIR; use crate::device::block_device_handler::get_virtio_blk_pci_device_name; #[cfg(target_arch = "s390x")] use crate::device::network_device_handler::wait_for_ccw_net_interface; @@ -65,9 +66,6 @@ use crate::device::network_device_handler::wait_for_ccw_net_interface; use crate::device::network_device_handler::wait_for_pci_net_interface; use crate::device::{add_devices, handle_cdi_devices, update_env_pci}; use crate::features::get_build_features; -#[cfg(feature = "guest-pull")] -use crate::image::KATA_IMAGE_WORK_DIR; -use crate::linux_abi::*; use crate::metrics::get_metrics; use crate::mount::baremount; use crate::namespace::{NSTYPEIPC, NSTYPEPID, NSTYPEUTS}; @@ -80,6 +78,7 @@ use crate::storage::{add_storages, update_ephemeral_mounts, STORAGE_HANDLERS}; use crate::util; use crate::version::{AGENT_VERSION, API_VERSION}; use crate::AGENT_CONFIG; +use crate::{confidential_data_hub, linux_abi::*}; use crate::trace_rpc_call; use crate::tracer::extract_carrier_from_ttrpc; @@ -87,9 +86,6 @@ use crate::tracer::extract_carrier_from_ttrpc; #[cfg(feature = "agent-policy")] use crate::policy::{do_set_policy, is_allowed}; -#[cfg(feature = "guest-pull")] -use crate::image; - use opentelemetry::global; use tracing::span; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -322,7 +318,8 @@ impl AgentService { let p = if let Some(p) = oci.process() { #[cfg(feature = "guest-pull")] { - let new_p = image::get_process(p, &oci, req.storages.clone())?; + let new_p = + confidential_data_hub::image::get_process(p, &oci, req.storages.clone())?; Process::new(&sl(), &new_p, cid.as_str(), true, pipe_size, proc_io)? } @@ -1331,9 +1328,10 @@ impl agent_ttrpc::AgentService for AgentService { s.network.set_dns(dns); } } - #[cfg(feature = "guest-pull")] - image::init_image_service().await.map_ttrpc_err(same)?; + confidential_data_hub::image::init_image_service() + .await + .map_ttrpc_err(same)?; Ok(Empty::new()) } @@ -2274,9 +2272,8 @@ fn is_sealed_secret_path(source_path: &str) -> bool { .any(|suffix| source_path.ends_with(suffix)) } -#[cfg(feature = "guest-pull")] async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> { - if !cdh::is_cdh_client_initialized().await { + if !confidential_data_hub::is_cdh_client_initialized() { return Ok(()); } let linux = oci @@ -2301,7 +2298,13 @@ async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> { ("encryptType".to_string(), "LUKS".to_string()), ("dataIntegrity".to_string(), secure_storage_integrity), ]); - cdh::secure_mount("BlockDevice", &options, vec![], KATA_IMAGE_WORK_DIR).await?; + confidential_data_hub::secure_mount( + "BlockDevice", + &options, + vec![], + KATA_IMAGE_WORK_DIR, + ) + .await?; break; } } @@ -2310,7 +2313,7 @@ async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> { } async fn cdh_handler_sealed_secrets(oci: &mut Spec) -> Result<()> { - if !cdh::is_cdh_client_initialized().await { + if !confidential_data_hub::is_cdh_client_initialized() { return Ok(()); } let process = oci @@ -2319,7 +2322,7 @@ async fn cdh_handler_sealed_secrets(oci: &mut Spec) -> Result<()> { .ok_or_else(|| anyhow!("Spec didn't contain process field"))?; if let Some(envs) = process.env_mut().as_mut() { for env in envs.iter_mut() { - match cdh::unseal_env(env).await { + match confidential_data_hub::unseal_env(env).await { Ok(unsealed_env) => *env = unsealed_env.to_string(), Err(e) => { warn!(sl(), "Failed to unseal secret: {}", e) @@ -2357,7 +2360,7 @@ async fn cdh_handler_sealed_secrets(oci: &mut Spec) -> Result<()> { // But currently there is no quick way to determine which volume-mount is referring // to a sealed secret without reading the file. // And relying on file naming heuristic is inflexible. So we are going with this approach. - if let Err(e) = cdh::unseal_file(source_path).await { + if let Err(e) = confidential_data_hub::unseal_file(source_path).await { warn!( sl(), "Failed to unseal file: {:?}, Error: {:?}", source_path, e From 4436fe6d9964072de343f68db6a91128f4b24cbe Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 09:53:09 +0800 Subject: [PATCH 03/17] agent: move guest pull abilities to Confidential Data Hub Image pull abilities are all moved to the separate component Confidential Data Hub (CDH) and we only left the auxiliary functions except pull_image in confidential_data_hub/image.rs Signed-off-by: Xynnn007 --- src/agent/Cargo.lock | 2624 +----------------- src/agent/Cargo.toml | 6 - src/agent/src/confidential_data_hub/image.rs | 290 +- src/agent/src/confidential_data_hub/mod.rs | 69 +- 4 files changed, 171 insertions(+), 2818 deletions(-) diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 4ea5dbb5bb..c5fe85543b 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -17,51 +17,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "zeroize", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aes-kw" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c" -dependencies = [ - "aes", -] - [[package]] name = "ahash" version = "0.7.8" @@ -181,55 +136,12 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "astral-tokio-tar" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65152cbda42e8ab5ecff69e8811e8333d69188c7d5c41e3eedb8d127e3f23b27" -dependencies = [ - "filetime", - "futures-core", - "libc", - "portable-atomic", - "rustc-hash 2.1.1", - "tokio", - "tokio-stream", - "xattr 1.5.0", -] - [[package]] name = "async-attributes" version = "1.1.2" @@ -281,12 +193,9 @@ checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07" dependencies = [ "flate2", "futures-core", - "futures-io", "memchr", "pin-project-lite", "tokio", - "zstd", - "zstd-safe", ] [[package]] @@ -496,26 +405,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "attester" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "anyhow", - "async-trait", - "base64 0.22.1", - "cfg-if", - "hex", - "kbs-types", - "log", - "serde", - "serde_json", - "serde_with", - "sha2", - "strum 0.27.1", - "thiserror 2.0.12", -] - [[package]] name = "atty" version = "0.2.14" @@ -554,46 +443,18 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-serde" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba368df5de76a5bea49aaf0cf1b39ccfbbef176924d1ba5db3e4135216cbe3c7" -dependencies = [ - "base64 0.21.7", - "serde", -] - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - [[package]] name = "bincode" version = "1.3.3" @@ -603,32 +464,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.63.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 1.0.109", -] - -[[package]] -name = "binstring" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a3c2603413428303761fae99d4b6d936404208221a44eba47d7c1e6dd03a3" - [[package]] name = "bit-set" version = "0.5.3" @@ -678,26 +513,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "blake2b_simd" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -707,15 +522,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.6.1" @@ -729,16 +535,6 @@ dependencies = [ "piper", ] -[[package]] -name = "blowfish" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" -dependencies = [ - "byteorder", - "cipher", -] - [[package]] name = "borsh" version = "1.5.7" @@ -762,17 +558,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "buffered-reader" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db26bf1f092fd5e05b5ab3be2f290915aeb6f3f20c4e9f86ce0f07f336c2412f" -dependencies = [ - "bzip2", - "flate2", - "libc", -] - [[package]] name = "bumpalo" version = "3.17.0" @@ -840,35 +625,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "camellia" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" -dependencies = [ - "byteorder", - "cipher", -] - [[package]] name = "capctl" version = "0.2.4" @@ -890,32 +646,12 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "cast5" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" -dependencies = [ - "cipher", -] - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" version = "1.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" dependencies = [ - "jobserver", - "libc", "shlex", ] @@ -932,7 +668,7 @@ dependencies = [ "libc", "nix 0.24.3", "notify", - "oci-spec 0.6.8", + "oci-spec", "once_cell", "path-clean", "regex", @@ -943,30 +679,6 @@ dependencies = [ "serde_yaml", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - -[[package]] -name = "cfb-mode" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" -dependencies = [ - "cipher", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -1001,33 +713,10 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", - "serde", "wasm-bindgen", "windows-link", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "3.2.25" @@ -1107,59 +796,18 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" -[[package]] -name = "cmac" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" -dependencies = [ - "cipher", - "dbl", - "digest", -] - -[[package]] -name = "coarsetime" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4" -dependencies = [ - "libc", - "wasix", - "wasm-bindgen", -] - [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes 1.10.1", - "memchr", -] - [[package]] name = "common-path" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" -[[package]] -name = "concat-kdf" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d72c1252426a83be2092dd5884a5f6e3b8e7180f6891b6263d2c21b92ec8816" -dependencies = [ - "digest", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1169,12 +817,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "const_format" version = "0.2.34" @@ -1195,51 +837,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" -dependencies = [ - "cookie", - "document-features", - "idna", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1320,47 +917,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "aes-gcm", - "aes-kw", - "anyhow", - "base64 0.22.1", - "concat-kdf", - "ctr", - "kbs-types", - "p256", - "rand 0.8.5", - "rand 0.9.1", - "rsa", - "serde", - "serde_json", - "sha2", - "strum 0.27.1", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -1368,67 +924,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] -[[package]] -name = "crypto_secretbox" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" -dependencies = [ - "aead", - "cipher", - "generic-array", - "poly1305", - "salsa20", - "subtle", - "zeroize", -] - -[[package]] -name = "ct-codecs" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0d274c65cbc1c34703d2fc2ce0fb892ff68f4516b677671a2f238a30b9b2b2" - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "darling" version = "0.14.4" @@ -1498,45 +996,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "dbl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" -dependencies = [ - "generic-array", -] - -[[package]] -name = "decoded-char" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5440d1dc8ea7cae44cda3c64568db29bfa2434aba51ae66a50c00488841a65a3" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "der_derive", - "flagset", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "der_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "deranged" version = "0.4.0" @@ -1544,7 +1003,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -1600,15 +1058,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "des" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" -dependencies = [ - "cipher", -] - [[package]] name = "digest" version = "0.10.7" @@ -1616,9 +1065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", "crypto-common", - "subtle", ] [[package]] @@ -1653,150 +1100,18 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "document-features" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" -dependencies = [ - "litrs", -] - [[package]] name = "downcast" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" -[[package]] -name = "dsa" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" -dependencies = [ - "digest", - "num-bigint-dig", - "num-traits", - "pkcs8", - "rfc6979", - "sha2", - "signature", - "zeroize", -] - -[[package]] -name = "dyn-clone" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" - -[[package]] -name = "eax" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" -dependencies = [ - "aead", - "cipher", - "cmac", - "ctr", - "subtle", -] - -[[package]] -name = "ecb" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" -dependencies = [ - "cipher", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-compact" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" -dependencies = [ - "ct-codecs", - "getrandom 0.2.16", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core 0.6.4", - "serde", - "sha2", - "subtle", - "zeroize", -] - [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ena" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" -dependencies = [ - "log", -] - [[package]] name = "enumflags2" version = "0.7.11" @@ -1824,17 +1139,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - [[package]] name = "errno" version = "0.3.11" @@ -1845,16 +1149,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -1901,7 +1195,7 @@ checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c" dependencies = [ "log", "once_cell", - "rand 0.8.5", + "rand", ] [[package]] @@ -1930,22 +1224,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "filetime" version = "0.2.25" @@ -1964,18 +1242,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flagset" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" - [[package]] name = "flate2" version = "1.1.1" @@ -2172,7 +1438,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -2195,11 +1460,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", - "wasm-bindgen", ] [[package]] @@ -2214,16 +1477,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - [[package]] name = "gimli" version = "0.31.1" @@ -2248,17 +1501,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -2328,48 +1570,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "hmac-sha1-compact" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18492c9f6f9a560e0d346369b665ad2bdbc89fa9bceca75796584e79042694c3" - -[[package]] -name = "hmac-sha256" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8575493d277c9092b988c780c94737fb9fd8651a1001e16bee3eccfc1baedb" -dependencies = [ - "digest", -] - -[[package]] -name = "hmac-sha512" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b3a0f572aa8389d325f5852b9e0a333a15b0f86ecccbb3fdb6e97cd86dc67c" -dependencies = [ - "digest", -] - [[package]] name = "home" version = "0.5.9" @@ -2390,15 +1590,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-auth" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "150fa4a9462ef926824cf4519c84ed652ca8f4fbae34cb8af045b5cbcaf98822" -dependencies = [ - "memchr", -] - [[package]] name = "http-body" version = "1.0.1" @@ -2447,25 +1638,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots 0.26.11", -] - [[package]] name = "hyper-util" version = "0.1.11" @@ -2628,15 +1800,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "idea" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" -dependencies = [ - "cipher", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2664,50 +1827,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "image-rs" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "anyhow", - "astral-tokio-tar", - "async-compression", - "async-trait", - "base64 0.22.1", - "cfg-if", - "filetime", - "flate2", - "futures", - "futures-util", - "hex", - "kbc", - "log", - "loopdev", - "nix 0.29.0", - "oci-client", - "oci-spec 0.8.1", - "ocicrypt-rs", - "protobuf 3.7.1", - "reqwest", - "sequoia-openpgp", - "serde", - "serde_json", - "serde_yaml", - "sha2", - "sigstore", - "strum 0.27.1", - "strum_macros 0.27.1", - "tokio", - "tokio-util", - "toml 0.8.22", - "ttrpc", - "ttrpc-codegen", - "url", - "walkdir", - "xattr 1.5.0", - "zstd", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -2716,7 +1835,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde", ] [[package]] @@ -2727,7 +1845,6 @@ checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.3", - "serde", ] [[package]] @@ -2752,16 +1869,6 @@ dependencies = [ "libc", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "block-padding", - "generic-array", -] - [[package]] name = "instant" version = "0.1.13" @@ -2841,53 +1948,12 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - [[package]] name = "js-sys" version = "0.3.77" @@ -2898,18 +1964,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json-number" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66994b2bac615128d07a1e4527ad29e98b004dd1a1769e7b8fbc1173ccf43006" -dependencies = [ - "lexical", - "ryu-js", - "serde", - "smallvec", -] - [[package]] name = "json-patch" version = "2.0.0" @@ -2922,25 +1976,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "json-syntax" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044a68aba3f96d712f492b72be25e10f96201eaaca3207a7d6e68d6d5105fda9" -dependencies = [ - "decoded-char", - "hashbrown 0.12.3", - "indexmap 1.9.3", - "json-number", - "locspan", - "locspan-derive", - "ryu-js", - "serde", - "smallstr", - "smallvec", - "utf8-decode", -] - [[package]] name = "jsonptr" version = "0.4.7" @@ -2982,61 +2017,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "jwt" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" -dependencies = [ - "base64 0.13.1", - "crypto-common", - "digest", - "hmac", - "serde", - "serde_json", - "sha2", -] - -[[package]] -name = "jwt-simple" -version = "0.12.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731011e9647a71ff4f8474176ff6ce6e0d2de87a0173f15613af3a84c3e3401a" -dependencies = [ - "anyhow", - "binstring", - "blake2b_simd", - "coarsetime", - "ct-codecs", - "ed25519-compact", - "hmac-sha1-compact", - "hmac-sha256", - "hmac-sha512", - "k256", - "p256", - "p384", - "rand 0.8.5", - "serde", - "serde_json", - "superboring", - "thiserror 2.0.12", - "zeroize", -] - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", - "signature", -] - [[package]] name = "kata-agent" version = "0.1.0" @@ -3055,7 +2035,6 @@ dependencies = [ "const_format", "derivative", "futures", - "image-rs", "ipnetwork", "kata-agent-policy", "kata-sys-util", @@ -3069,7 +2048,7 @@ dependencies = [ "netlink-packet-route", "netlink-sys 0.7.0", "nix 0.24.3", - "oci-spec 0.6.8", + "oci-spec", "opentelemetry", "procfs 0.12.0", "prometheus", @@ -3092,14 +2071,14 @@ dependencies = [ "slog-scope", "slog-stdlog", "slog-term", - "strum 0.26.3", - "strum_macros 0.26.4", + "strum", + "strum_macros", "tempfile", "test-utils", "thiserror 1.0.69", "tokio", "tokio-vsock 0.3.4", - "toml 0.5.11", + "toml", "tracing", "tracing-opentelemetry", "tracing-subscriber", @@ -3138,10 +2117,10 @@ dependencies = [ "libc", "mockall", "nix 0.24.3", - "oci-spec 0.6.8", + "oci-spec", "once_cell", "pci-ids", - "rand 0.8.5", + "rand", "runtime-spec", "safe-path", "serde", @@ -3163,7 +2142,7 @@ dependencies = [ "glob", "lazy_static", "num_cpus", - "oci-spec 0.6.8", + "oci-spec", "regex", "safe-path", "serde", @@ -3173,71 +2152,7 @@ dependencies = [ "slog-scope", "sysinfo", "thiserror 1.0.69", - "toml 0.5.11", -] - -[[package]] -name = "kbc" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "anyhow", - "async-trait", - "base64 0.22.1", - "crypto", - "kbs_protocol", - "log", - "resource_uri", - "serde", - "serde_json", - "strum 0.27.1", - "url", - "zeroize", -] - -[[package]] -name = "kbs-types" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db954f164e19a63a1eb7c04c46511167d68a5eb5025d4a435c1ba297f00dbf4" -dependencies = [ - "base64 0.22.1", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[package]] -name = "kbs_protocol" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "anyhow", - "async-trait", - "attester", - "base64 0.22.1", - "crypto", - "jwt-simple", - "kbs-types", - "log", - "reqwest", - "resource_uri", - "serde", - "serde_json", - "sha2", - "thiserror 2.0.12", - "tokio", - "url", - "zeroize", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", + "toml", ] [[package]] @@ -3269,123 +2184,11 @@ dependencies = [ "log", ] -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph 0.6.5", - "regex", - "regex-syntax 0.8.5", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata 0.4.9", -] - [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lexical" -version = "7.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ed980ff02623721dc334b9105150b66d0e1f246a92ab5a2eca0335d54c48f6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b765c31809609075565a70b4b71402281283aeda7ecaf4818ac14a7b2ade8958" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de6f9cb01fb0b08060209a057c048fcbab8717b4c1ecd2eac66ebfe39a65b0f2" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72207aae22fc0a121ba7b6d479e42cbfea549af1479c3f3a4f12c70dd66df12e" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a82e24bf537fd24c177ffbbdc6ebcc8d54732c35b50a3f28cc3f4e4c949a0b3" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5afc668a27f460fb45a81a757b6bf2f43c2d7e30cb5a2dcd3abf294c78d62bd" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629ddff1a914a836fb245616a7888b62903aae58fa771e1d83943035efa0f978" -dependencies = [ - "lexical-util", - "static_assertions", -] [[package]] name = "libc" @@ -3393,22 +2196,6 @@ version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.48.5", -] - -[[package]] -name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - [[package]] name = "libredox" version = "0.1.3" @@ -3462,12 +2249,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - [[package]] name = "lock_api" version = "0.4.12" @@ -3478,24 +2259,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "locspan" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33890449fcfac88e94352092944bf321f55e5deb4e289a6f51c87c55731200a0" - -[[package]] -name = "locspan-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88991223b049a3d29ca1f60c05639581336a0f3ee4bf8a659dddecc11c4961a" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "log" version = "0.4.27" @@ -3519,22 +2282,6 @@ dependencies = [ "slog-term", ] -[[package]] -name = "loopdev" -version = "0.5.0" -source = "git+https://github.com/mdaffin/loopdev?rev=c9f91e8f0326ce8a3364ac911e81eb32328a5f27#c9f91e8f0326ce8a3364ac911e81eb32328a5f27" -dependencies = [ - "bindgen", - "errno 0.2.8", - "libc", -] - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "matchers" version = "0.0.1" @@ -3544,16 +2291,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - [[package]] name = "mem-agent" version = "0.1.0" @@ -3602,12 +2339,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memsec" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492" - [[package]] name = "mime" version = "0.3.17" @@ -3684,12 +2415,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - [[package]] name = "netlink-packet-core" version = "0.7.0" @@ -3766,12 +2491,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nix" version = "0.23.2" @@ -3833,18 +2552,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -3916,23 +2623,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.5", - "smallvec", - "zeroize", -] - [[package]] name = "num-cmp" version = "0.1.0" @@ -3992,7 +2682,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -4005,15 +2694,6 @@ dependencies = [ "libc", ] -[[package]] -name = "objc2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" -dependencies = [ - "objc2-encode", -] - [[package]] name = "objc2-core-foundation" version = "0.3.1" @@ -4023,22 +2703,6 @@ dependencies = [ "bitflags 2.9.0", ] -[[package]] -name = "objc2-encode" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" - -[[package]] -name = "objc2-foundation" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" -dependencies = [ - "bitflags 2.9.0", - "objc2", -] - [[package]] name = "object" version = "0.36.7" @@ -4048,44 +2712,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ocb3" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c196e0276c471c843dd5777e7543a36a298a4be942a2a688d8111cd43390dedb" -dependencies = [ - "aead", - "cipher", - "ctr", - "subtle", -] - -[[package]] -name = "oci-client" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474675fdc023fbcc9dcf4782e938a3a1ae5fd469c728d8db40599bd25c77e1ba" -dependencies = [ - "bytes 1.10.1", - "chrono", - "futures-util", - "http", - "http-auth", - "jwt", - "lazy_static", - "oci-spec 0.7.1", - "olpc-cjson", - "regex", - "reqwest", - "serde", - "serde_json", - "sha2", - "thiserror 1.0.69", - "tokio", - "tracing", - "unicase", -] - [[package]] name = "oci-spec" version = "0.6.8" @@ -4098,97 +2724,17 @@ dependencies = [ "regex", "serde", "serde_json", - "strum 0.26.3", - "strum_macros 0.26.4", + "strum", + "strum_macros", "thiserror 1.0.69", ] -[[package]] -name = "oci-spec" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da406e58efe2eb5986a6139626d611ce426e5324a824133d76367c765cf0b882" -dependencies = [ - "derive_builder", - "getset", - "regex", - "serde", - "serde_json", - "strum 0.26.3", - "strum_macros 0.26.4", - "thiserror 2.0.12", -] - -[[package]] -name = "oci-spec" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e9beda9d92fac7bf4904c34c83340ef1024159faee67179a04e0277523da33" -dependencies = [ - "const_format", - "derive_builder", - "getset", - "regex", - "serde", - "serde_json", - "strum 0.27.1", - "strum_macros 0.27.1", - "thiserror 2.0.12", -] - -[[package]] -name = "ocicrypt-rs" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "aes", - "anyhow", - "async-trait", - "base64 0.22.1", - "base64-serde", - "cfg-if", - "ctr", - "hmac", - "kbc", - "pin-project-lite", - "protobuf 3.7.1", - "ring", - "serde", - "serde_json", - "sha2", - "tokio", - "ttrpc", -] - -[[package]] -name = "olpc-cjson" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "696183c9b5fe81a7715d074fd632e8bd46f4ccc0231a3ed7fc580a80de5f7083" -dependencies = [ - "serde", - "serde_json", - "unicode-normalization", -] - [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "opentelemetry" version = "0.14.0" @@ -4202,7 +2748,7 @@ dependencies = [ "lazy_static", "percent-encoding", "pin-project", - "rand 0.8.5", + "rand", "serde", "thiserror 1.0.69", "tokio", @@ -4225,44 +2771,6 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p384" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p521" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" -dependencies = [ - "base16ct", - "ecdsa", - "elliptic-curve", - "primeorder", - "rand_core 0.6.4", - "sha2", -] - [[package]] name = "page_size" version = "0.6.0" @@ -4327,17 +2835,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "paste" version = "1.0.15" @@ -4369,16 +2866,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - [[package]] name = "pci-ids" version = "0.2.5" @@ -4392,31 +2879,6 @@ dependencies = [ "quote", ] -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -4429,20 +2891,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ - "fixedbitset 0.2.0", + "fixedbitset", "indexmap 1.9.3", ] -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset 0.4.2", - "indexmap 2.9.0", -] - [[package]] name = "phf" version = "0.11.3" @@ -4469,7 +2921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand", ] [[package]] @@ -4524,44 +2976,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der", - "pbkdf2", - "scrypt", - "sha2", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "pkcs5", - "rand_core 0.6.4", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.32" @@ -4599,35 +3013,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - [[package]] name = "powerfmt" version = "0.2.0" @@ -4643,12 +3028,6 @@ dependencies = [ "zerocopy 0.8.25", ] -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "predicates" version = "3.1.3" @@ -4675,15 +3054,6 @@ dependencies = [ "termtree", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -4831,10 +3201,10 @@ checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ "bytes 1.10.1", "heck 0.3.3", - "itertools 0.10.5", + "itertools", "log", "multimap", - "petgraph 0.5.1", + "petgraph", "prost", "prost-types", "tempfile", @@ -4848,7 +3218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools", "proc-macro2", "quote", "syn 1.0.109", @@ -4935,7 +3305,7 @@ name = "protocols" version = "0.1.0" dependencies = [ "async-trait", - "oci-spec 0.6.8", + "oci-spec", "protobuf 3.7.1", "serde", "serde_json", @@ -4943,12 +3313,6 @@ dependencies = [ "ttrpc-codegen", ] -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - [[package]] name = "ptr_meta" version = "0.1.4" @@ -4969,71 +3333,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "publicsuffix" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" -dependencies = [ - "idna", - "psl-types", -] - -[[package]] -name = "quinn" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" -dependencies = [ - "bytes 1.10.1", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls", - "socket2 0.5.9", - "thiserror 2.0.12", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" -dependencies = [ - "bytes 1.10.1", - "getrandom 0.3.3", - "lru-slab", - "rand 0.9.1", - "ring", - "rustc-hash 2.1.1", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.9", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "quote" version = "1.0.40" @@ -5062,18 +3361,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_chacha", + "rand_core", ] [[package]] @@ -5083,17 +3372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", + "rand_core", ] [[package]] @@ -5105,15 +3384,6 @@ dependencies = [ "getrandom 0.2.16", ] -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -5195,7 +3465,7 @@ checksum = "843c3d97f07e3b5ac0955d53ad0af4c91fe4a4f8525843ece5bf014f27829b73" dependencies = [ "anyhow", "lazy_static", - "rand 0.8.5", + "rand", "regex", "scientific", "serde", @@ -5225,8 +3495,6 @@ checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64 0.22.1", "bytes 1.10.1", - "cookie", - "cookie_store", "futures-channel", "futures-core", "futures-util", @@ -5234,7 +3502,6 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", "ipnet", "js-sys", @@ -5243,73 +3510,20 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-native-certs", - "rustls-pemfile", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", - "tokio-util", "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", "web-sys", - "webpki-roots 0.26.11", "windows-registry", ] -[[package]] -name = "resource_uri" -version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components?rev=0a06ef241190780840fbb0542e51b198f1f72b0b#0a06ef241190780840fbb0542e51b198f1f72b0b" -dependencies = [ - "anyhow", - "serde", - "serde_json", - "url", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest", -] - [[package]] name = "rkyv" version = "0.7.45" @@ -5348,27 +3562,6 @@ dependencies = [ "libc", ] -[[package]] -name = "rsa" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "sha2", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rstest" version = "0.18.2" @@ -5436,7 +3629,7 @@ dependencies = [ "borsh", "bytes 1.10.1", "num-traits", - "rand 0.8.5", + "rand", "rkyv", "serde", "serde_json", @@ -5448,18 +3641,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -5476,7 +3657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" dependencies = [ "bitflags 1.3.2", - "errno 0.3.11", + "errno", "io-lifetimes", "libc", "linux-raw-sys 0.3.8", @@ -5490,7 +3671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.9.0", - "errno 0.3.11", + "errno", "libc", "linux-raw-sys 0.4.15", "windows-sys 0.59.0", @@ -5503,7 +3684,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags 2.9.0", - "errno 0.3.11", + "errno", "libc", "linux-raw-sys 0.9.4", "windows-sys 0.59.0", @@ -5528,7 +3709,7 @@ dependencies = [ "libc", "libseccomp", "nix 0.24.3", - "oci-spec 0.6.8", + "oci-spec", "path-absolutize", "protobuf 3.7.1", "protocols", @@ -5547,77 +3728,10 @@ dependencies = [ "test-utils", "tokio", "tokio-vsock 0.3.4", - "xattr 0.2.3", + "xattr", "zbus", ] -[[package]] -name = "rustls" -version = "0.23.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki 0.103.3", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.20" @@ -5630,12 +3744,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "ryu-js" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" - [[package]] name = "s390_pv_core" version = "0.11.0" @@ -5657,15 +3765,6 @@ dependencies = [ "libc", ] -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -5684,15 +3783,6 @@ dependencies = [ "regex", ] -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "scientific" version = "0.5.3" @@ -5719,127 +3809,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "password-hash", - "pbkdf2", - "salsa20", - "sha2", -] - [[package]] name = "seahash" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" -dependencies = [ - "bitflags 2.9.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" -[[package]] -name = "sequoia-openpgp" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015e5fc3d023418b9db98ca9a7f3e90b305872eeafe5ca45c5c32b5eb335c1e8" -dependencies = [ - "aes", - "aes-gcm", - "anyhow", - "argon2", - "base64 0.22.1", - "block-padding", - "blowfish", - "buffered-reader", - "bzip2", - "camellia", - "cast5", - "cfb-mode", - "chrono", - "cipher", - "des", - "digest", - "dsa", - "dyn-clone", - "eax", - "ecb", - "ecdsa", - "ed25519", - "ed25519-dalek", - "flate2", - "getrandom 0.2.16", - "hkdf", - "idea", - "idna", - "lalrpop", - "lalrpop-util", - "libc", - "md-5", - "memsec", - "num-bigint-dig", - "ocb3", - "p256", - "p384", - "p521", - "rand 0.8.5", - "rand_core 0.6.4", - "regex", - "regex-syntax 0.8.5", - "ripemd", - "rsa", - "sha1collisiondetection", - "sha2", - "sha3", - "thiserror 2.0.12", - "twofish", - "typenum", - "x25519-dalek", - "xxhash-rust", -] - [[package]] name = "serde" version = "1.0.219" @@ -5913,15 +3894,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -5934,36 +3906,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -6010,17 +3952,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha1collisiondetection" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f606421e4a6012877e893c399822a4ed4b089164c5969424e1b9d1e66e6964b" -dependencies = [ - "const-oid", - "digest", - "generic-array", -] - [[package]] name = "sha2" version = "0.10.9" @@ -6032,16 +3963,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -6066,66 +3987,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core 0.6.4", -] - -[[package]] -name = "sigstore" -version = "0.11.0" -source = "git+https://github.com/sigstore/sigstore-rs.git?rev=c39c519#c39c519dd99be23f18e6143dd233b46bf2096e4d" -dependencies = [ - "async-trait", - "base64 0.22.1", - "cfg-if", - "chrono", - "const-oid", - "crypto_secretbox", - "digest", - "ecdsa", - "ed25519", - "ed25519-dalek", - "elliptic-curve", - "futures", - "getrandom 0.2.16", - "hex", - "json-syntax", - "lazy_static", - "oci-client", - "olpc-cjson", - "p256", - "p384", - "pem", - "pkcs1", - "pkcs8", - "rand 0.8.5", - "regex", - "ring", - "rsa", - "rustls-webpki 0.102.8", - "scrypt", - "serde", - "serde_json", - "serde_repr", - "sha2", - "signature", - "thiserror 2.0.12", - "tls_codec", - "tokio", - "tokio-util", - "tracing", - "url", - "webbrowser", - "x509-cert", - "zeroize", -] - [[package]] name = "simdutf8" version = "0.1.5" @@ -6218,16 +4079,6 @@ dependencies = [ "time", ] -[[package]] -name = "smallstr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b1aefdf380735ff8ded0b15f31aab05daf1f70216c01c02a12926badd1df9d" -dependencies = [ - "serde", - "smallvec", -] - [[package]] name = "smallvec" version = "1.15.0" @@ -6254,22 +4105,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -6282,18 +4117,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "string_cache" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" -dependencies = [ - "new_debug_unreachable", - "parking_lot 0.12.3", - "phf_shared", - "precomputed-hash", -] - [[package]] name = "strsim" version = "0.10.0" @@ -6312,15 +4135,6 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -[[package]] -name = "strum" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" -dependencies = [ - "strum_macros 0.27.1", -] - [[package]] name = "strum_macros" version = "0.26.4" @@ -6334,19 +4148,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "strum_macros" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.101", -] - [[package]] name = "subprocess" version = "0.2.9" @@ -6357,25 +4158,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "superboring" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "515cce34a781d7250b8a65706e0f2a5b99236ea605cb235d4baed6685820478f" -dependencies = [ - "getrandom 0.2.16", - "hmac-sha256", - "hmac-sha512", - "rand 0.8.5", - "rsa", -] - [[package]] name = "syn" version = "1.0.109" @@ -6576,15 +4358,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinystr" version = "0.7.6" @@ -6610,27 +4383,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tls_codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" -dependencies = [ - "tls_codec_derive", - "zeroize", -] - -[[package]] -name = "tls_codec_derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "tokio" version = "1.45.0" @@ -6660,16 +4412,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.17" @@ -6681,19 +4423,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-util" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" -dependencies = [ - "bytes 1.10.1", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-vsock" version = "0.3.4" @@ -6729,26 +4458,11 @@ dependencies = [ "serde", ] -[[package]] -name = "toml" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.26", -] - [[package]] name = "toml_datetime" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -6768,19 +4482,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap 2.9.0", - "serde", - "serde_spanned", "toml_datetime", - "toml_write", "winnow 0.7.10", ] -[[package]] -name = "toml_write" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" - [[package]] name = "tower" version = "0.5.2" @@ -6814,7 +4519,6 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6954,15 +4658,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "twofish" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" -dependencies = [ - "cipher", -] - [[package]] name = "typenum" version = "1.18.0" @@ -6980,27 +4675,12 @@ dependencies = [ "winapi", ] -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -7013,28 +4693,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - [[package]] name = "unsafe-libyaml" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.4" @@ -7052,12 +4716,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" -[[package]] -name = "utf8-decode" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca61eb27fa339aa08826a29f03e87b99b4d8f0fc2255306fd266bb1b6a9de498" - [[package]] name = "utf8-width" version = "0.1.7" @@ -7175,15 +4833,6 @@ dependencies = [ "wit-bindgen-rt", ] -[[package]] -name = "wasix" -version = "0.12.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" -dependencies = [ - "wasi 0.11.0+wasi-snapshot-preview1", -] - [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -7255,19 +4904,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.77" @@ -7278,51 +4914,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5df295f8451142f1856b1bd86a606dfe9587d439bc036e319c827700dbd555e" -dependencies = [ - "core-foundation", - "home", - "jni", - "log", - "ndk-context", - "objc2", - "objc2-foundation", - "url", - "web-sys", -] - -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.0", -] - -[[package]] -name = "webpki-roots" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "which" version = "4.4.2" @@ -7498,15 +5089,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -7534,21 +5116,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -7596,12 +5163,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -7620,12 +5181,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -7644,12 +5199,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -7680,12 +5229,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -7704,12 +5247,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -7728,12 +5265,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -7752,12 +5283,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -7824,31 +5349,6 @@ dependencies = [ "tap", ] -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core 0.6.4", - "zeroize", -] - -[[package]] -name = "x509-cert" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" -dependencies = [ - "const-oid", - "der", - "sha1", - "signature", - "spki", - "tls_codec", -] - [[package]] name = "xattr" version = "0.2.3" @@ -7858,16 +5358,6 @@ dependencies = [ "libc", ] -[[package]] -name = "xattr" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" -dependencies = [ - "libc", - "rustix 1.0.7", -] - [[package]] name = "xdg-home" version = "1.3.0" @@ -7878,12 +5368,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - [[package]] name = "yoke" version = "0.7.5" @@ -7935,7 +5419,7 @@ dependencies = [ "nix 0.26.4", "once_cell", "ordered-stream", - "rand 0.8.5", + "rand", "serde", "serde_repr", "sha1", @@ -8036,26 +5520,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "zerovec" version = "0.10.4" @@ -8078,34 +5542,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "zvariant" version = "3.15.2" diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml index 0d16c460bd..88c7ac3d67 100644 --- a/src/agent/Cargo.toml +++ b/src/agent/Cargo.toml @@ -162,9 +162,6 @@ clap.workspace = true strum.workspace = true strum_macros.workspace = true -# Image pull/decrypt -image-rs = { git = "https://github.com/confidential-containers/guest-components", rev = "0a06ef241190780840fbb0542e51b198f1f72b0b", default-features = false, optional = true } - # Agent Policy cdi = { git = "https://github.com/cncf-tags/container-device-interface-rs", rev = "fba5677a8e7cc962fc6e495fcec98d7d765e332a" } @@ -202,12 +199,9 @@ test-utils.workspace = true lto = true [features] -# The default-pull feature supports all sharing images by virtio-fs, for guest-pull build with the guest-pull feature -default-pull = [] seccomp = ["rustjail/seccomp"] standard-oci-runtime = ["rustjail/standard-oci-runtime"] agent-policy = ["kata-agent-policy"] -guest-pull = ["image-rs/kata-cc-rustls-tls"] [[bin]] name = "kata-agent" diff --git a/src/agent/src/confidential_data_hub/image.rs b/src/agent/src/confidential_data_hub/image.rs index 861ca3a5b9..2087b7a378 100644 --- a/src/agent/src/confidential_data_hub/image.rs +++ b/src/agent/src/confidential_data_hub/image.rs @@ -7,20 +7,14 @@ use safe_path::scoped_join; use std::collections::HashMap; -use std::env; use std::fs; use std::path::Path; -use std::sync::Arc; use anyhow::{anyhow, bail, Context, Result}; -use image_rs::builder::ClientBuilder; -use image_rs::image::ImageClient; use kata_sys_util::validate::verify_id; use oci_spec::runtime as oci; -use tokio::sync::Mutex; use crate::rpc::CONTAINER_BASE; -use crate::AGENT_CONFIG; use kata_types::mount::KATA_VIRTUAL_VOLUME_IMAGE_GUEST_PULL; use protocols::agent::Storage; @@ -34,17 +28,14 @@ const K8S_CONTAINER_TYPE_KEYS: [&str; 2] = [ "io.kubernetes.cri-o.ContainerType", ]; -#[rustfmt::skip] -lazy_static! { - pub static ref IMAGE_SERVICE: Arc>> = Arc::new(Mutex::new(None)); -} - // Convenience function to obtain the scope logger. fn sl() -> slog::Logger { slog_scope::logger().new(o!("subsystem" => "image")) } // Function to copy a file if it does not exist at the destination +// This function creates a dir, writes a file and if necessary, +// overwrites an existing file. fn copy_if_not_exists(src: &Path, dst: &Path) -> Result<()> { if let Some(dst_dir) = dst.parent() { fs::create_dir_all(dst_dir)?; @@ -53,175 +44,91 @@ fn copy_if_not_exists(src: &Path, dst: &Path) -> Result<()> { Ok(()) } -pub struct ImageService { - image_client: ImageClient, +/// get guest pause image process specification +fn get_pause_image_process() -> Result { + let guest_pause_bundle = Path::new(KATA_PAUSE_BUNDLE); + if !guest_pause_bundle.exists() { + bail!("Pause image not present in rootfs"); + } + let guest_pause_config = scoped_join(guest_pause_bundle, CONFIG_JSON)?; + + let image_oci = oci::Spec::load(guest_pause_config.to_str().ok_or_else(|| { + anyhow!( + "Failed to load the guest pause image config from {:?}", + guest_pause_config + ) + })?) + .context("load image config file")?; + + let image_oci_process = image_oci.process().as_ref().ok_or_else(|| { + anyhow!("The guest pause image config does not contain a process specification. Please check the pause image.") + })?; + Ok(image_oci_process.clone()) } -impl ImageService { - pub async fn new() -> Result { - let mut image_client_builder = - ClientBuilder::default().work_dir(KATA_IMAGE_WORK_DIR.into()); - #[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_builder = image_client_builder - .authenticated_registry_credentials_uri(registry_auth.into()); - } +/// pause image is packaged in rootfs +pub fn unpack_pause_image(cid: &str) -> Result { + verify_id(cid).context("The guest pause image cid contains invalid characters.")?; - let enable_signature_verification = &AGENT_CONFIG.enable_signature_verification; - debug!( - sl(), - "Enable image signature verification: {:?}", enable_signature_verification - ); - if !AGENT_CONFIG.image_policy_file.is_empty() && *enable_signature_verification { - let image_policy_file = &AGENT_CONFIG.image_policy_file; - debug!(sl(), "Use image policy file {:?}", image_policy_file); - image_client_builder = - image_client_builder.image_security_policy_uri(image_policy_file.into()); - } - } - let image_client = image_client_builder.build().await?; - Ok(Self { image_client }) + let guest_pause_bundle = Path::new(KATA_PAUSE_BUNDLE); + if !guest_pause_bundle.exists() { + bail!("Pause image not present in rootfs"); } + let guest_pause_config = scoped_join(guest_pause_bundle, CONFIG_JSON)?; + info!(sl(), "use guest pause image cid {:?}", cid); - /// get guest pause image process specification - fn get_pause_image_process() -> Result { - let guest_pause_bundle = Path::new(KATA_PAUSE_BUNDLE); - if !guest_pause_bundle.exists() { - bail!("Pause image not present in rootfs"); - } - let guest_pause_config = scoped_join(guest_pause_bundle, CONFIG_JSON)?; + let image_oci = oci::Spec::load(guest_pause_config.to_str().ok_or_else(|| { + anyhow!( + "Failed to load the guest pause image config from {:?}", + guest_pause_config + ) + })?) + .context("load image config file")?; - let image_oci = oci::Spec::load(guest_pause_config.to_str().ok_or_else(|| { - anyhow!( - "Failed to load the guest pause image config from {:?}", - guest_pause_config - ) - })?) - .context("load image config file")?; - - let image_oci_process = image_oci.process().as_ref().ok_or_else(|| { + let image_oci_process = image_oci.process().as_ref().ok_or_else(|| { anyhow!("The guest pause image config does not contain a process specification. Please check the pause image.") })?; - Ok(image_oci_process.clone()) - } + info!( + sl(), + "pause image oci process {:?}", + image_oci_process.clone() + ); - /// pause image is packaged in rootfs - fn unpack_pause_image(cid: &str) -> Result { - verify_id(cid).context("The guest pause image cid contains invalid characters.")?; + // Ensure that the args vector is not empty before accessing its elements. + // Check the number of arguments. + let args = if let Some(args_vec) = image_oci_process.args() { + args_vec + } else { + bail!("The number of args should be greater than or equal to one! Please check the pause image."); + }; - let guest_pause_bundle = Path::new(KATA_PAUSE_BUNDLE); - if !guest_pause_bundle.exists() { - bail!("Pause image not present in rootfs"); - } - let guest_pause_config = scoped_join(guest_pause_bundle, CONFIG_JSON)?; - info!(sl(), "use guest pause image cid {:?}", cid); + let pause_bundle = scoped_join(CONTAINER_BASE, cid)?; + fs::create_dir_all(&pause_bundle)?; + let pause_rootfs = scoped_join(&pause_bundle, "rootfs")?; + fs::create_dir_all(&pause_rootfs)?; + info!(sl(), "pause_rootfs {:?}", pause_rootfs); - let image_oci = oci::Spec::load(guest_pause_config.to_str().ok_or_else(|| { - anyhow!( - "Failed to load the guest pause image config from {:?}", - guest_pause_config - ) - })?) - .context("load image config file")?; + copy_if_not_exists(&guest_pause_config, &pause_bundle.join(CONFIG_JSON))?; + let arg_path = Path::new(&args[0]).strip_prefix("/")?; + copy_if_not_exists( + &guest_pause_bundle.join("rootfs").join(arg_path), + &pause_rootfs.join(arg_path), + )?; + Ok(pause_rootfs.display().to_string()) +} - let image_oci_process = image_oci.process().as_ref().ok_or_else(|| { - anyhow!("The guest pause image config does not contain a process specification. Please check the pause image.") - })?; - info!( - sl(), - "pause image oci process {:?}", - image_oci_process.clone() - ); - - // Ensure that the args vector is not empty before accessing its elements. - // Check the number of arguments. - let args = if let Some(args_vec) = image_oci_process.args() { - args_vec - } else { - bail!("The number of args should be greater than or equal to one! Please check the pause image."); - }; - - let pause_bundle = scoped_join(CONTAINER_BASE, cid)?; - fs::create_dir_all(&pause_bundle)?; - let pause_rootfs = scoped_join(&pause_bundle, "rootfs")?; - fs::create_dir_all(&pause_rootfs)?; - info!(sl(), "pause_rootfs {:?}", pause_rootfs); - - copy_if_not_exists(&guest_pause_config, &pause_bundle.join(CONFIG_JSON))?; - let arg_path = Path::new(&args[0]).strip_prefix("/")?; - copy_if_not_exists( - &guest_pause_bundle.join("rootfs").join(arg_path), - &pause_rootfs.join(arg_path), - )?; - Ok(pause_rootfs.display().to_string()) - } - - /// check whether the image is for sandbox or for container. - fn is_sandbox(image_metadata: &HashMap) -> bool { - let mut is_sandbox = false; - for key in K8S_CONTAINER_TYPE_KEYS.iter() { - if let Some(value) = image_metadata.get(key as &str) { - if value == "sandbox" { - is_sandbox = true; - break; - } +/// check whether the image is for sandbox or for container. +pub fn is_sandbox(image_metadata: &HashMap) -> bool { + let mut is_sandbox = false; + for key in K8S_CONTAINER_TYPE_KEYS.iter() { + if let Some(value) = image_metadata.get(key as &str) { + if value == "sandbox" { + is_sandbox = true; + break; } } - is_sandbox - } - - /// pull_image is used for call image-rs to pull image in the guest. - /// # Parameters - /// - `image`: Image name (exp: quay.io/prometheus/busybox:latest) - /// - `cid`: Container id - /// - `image_metadata`: Annotations about the image (exp: "containerd.io/snapshot/cri.layer-digest": "sha256:24fb2886d6f6c5d16481dd7608b47e78a8e92a13d6e64d87d57cb16d5f766d63") - /// # Returns - /// - The image rootfs bundle path. (exp. /run/kata-containers/cb0b47276ea66ee9f44cc53afa94d7980b57a52c3f306f68cb034e58d9fbd3c6/rootfs) - pub async fn pull_image( - &mut self, - image: &str, - cid: &str, - image_metadata: &HashMap, - ) -> Result { - info!(sl(), "image metadata: {image_metadata:?}"); - - if Self::is_sandbox(image_metadata) { - let mount_path = Self::unpack_pause_image(cid)?; - return Ok(mount_path); - } - - // Image layers will store at KATA_IMAGE_WORK_DIR, generated bundles - // with rootfs and config.json will store under CONTAINER_BASE/cid/images. - let bundle_path = scoped_join(CONTAINER_BASE, cid)?; - fs::create_dir_all(&bundle_path)?; - info!(sl(), "pull image {image:?}, bundle path {bundle_path:?}"); - - let res = self - .image_client - .pull_image(image, &bundle_path, &None, &None) - .await; - match res { - Ok(image) => { - info!( - sl(), - "pull and unpack image {image:?}, cid: {cid:?} succeeded." - ); - } - Err(e) => { - error!( - sl(), - "pull and unpack image {image:?}, cid: {cid:?} failed with {:?}.", - e.to_string() - ); - return Err(e); - } - }; - let image_bundle_path = scoped_join(&bundle_path, "rootfs")?; - Ok(image_bundle_path.as_path().display().to_string()) } + is_sandbox } /// get_process overrides the OCI process spec with pause image process spec if needed @@ -239,58 +146,11 @@ pub fn get_process( } if guest_pull { if let Some(a) = oci.annotations() { - if ImageService::is_sandbox(a) { - return ImageService::get_pause_image_process(); + if is_sandbox(a) { + return get_pause_image_process(); } } } + Ok(ocip.clone()) } - -/// Set proxy environment from AGENT_CONFIG -pub async fn set_proxy_env_vars() { - if env::var("HTTPS_PROXY").is_err() { - let https_proxy = &AGENT_CONFIG.https_proxy; - if !https_proxy.is_empty() { - env::set_var("HTTPS_PROXY", https_proxy); - } - } - - match env::var("HTTPS_PROXY") { - Ok(val) => info!(sl(), "https_proxy is set to: {}", val), - Err(e) => info!(sl(), "https_proxy is not set ({})", e), - }; - - if env::var("NO_PROXY").is_err() { - let no_proxy = &AGENT_CONFIG.no_proxy; - if !no_proxy.is_empty() { - env::set_var("NO_PROXY", no_proxy); - } - } - - match env::var("NO_PROXY") { - Ok(val) => info!(sl(), "no_proxy is set to: {}", val), - Err(e) => info!(sl(), "no_proxy is not set ({})", e), - }; -} - -/// Init the image service -pub async fn init_image_service() -> Result<()> { - let image_service = ImageService::new().await?; - *IMAGE_SERVICE.lock().await = Some(image_service); - Ok(()) -} - -pub async fn pull_image( - image: &str, - cid: &str, - image_metadata: &HashMap, -) -> Result { - let image_service = IMAGE_SERVICE.clone(); - let mut image_service = image_service.lock().await; - let image_service = image_service - .as_mut() - .expect("Image Service not initialized"); - - image_service.pull_image(image, cid, image_metadata).await -} diff --git a/src/agent/src/confidential_data_hub/mod.rs b/src/agent/src/confidential_data_hub/mod.rs index 36468e9779..3cb48133ce 100644 --- a/src/agent/src/confidential_data_hub/mod.rs +++ b/src/agent/src/confidential_data_hub/mod.rs @@ -1,4 +1,5 @@ // Copyright (c) 2023 Intel Corporation +// Copyright (c) 2025 Alibaba Cloud // // SPDX-License-Identifier: Apache-2.0 // @@ -15,14 +16,18 @@ use protocols::{ confidential_data_hub::GetResourceRequest, confidential_data_hub_ttrpc_async, confidential_data_hub_ttrpc_async::{ - GetResourceServiceClient, SealedSecretServiceClient, SecureMountServiceClient, + GetResourceServiceClient, ImagePullServiceClient, SealedSecretServiceClient, + SecureMountServiceClient, }, }; +use safe_path::scoped_join; use std::fs; -use std::os::unix::fs::symlink; use std::path::Path; +use std::{os::unix::fs::symlink, path::PathBuf}; use tokio::sync::OnceCell; +pub mod image; + pub static CDH_CLIENT: OnceCell = OnceCell::const_new(); const SEALED_SECRET_PREFIX: &str = "sealed."; @@ -41,6 +46,8 @@ pub struct CDHClient { secure_mount_client: SecureMountServiceClient, #[derivative(Debug = "ignore")] get_resource_client: GetResourceServiceClient, + #[derivative(Debug = "ignore")] + image_pull_client: ImagePullServiceClient, } impl CDHClient { @@ -48,6 +55,8 @@ impl CDHClient { let client = ttrpc::asynchronous::Client::connect(cdh_socket_uri)?; let sealed_secret_client = confidential_data_hub_ttrpc_async::SealedSecretServiceClient::new(client.clone()); + let image_pull_client = + confidential_data_hub_ttrpc_async::ImagePullServiceClient::new(client.clone()); let secure_mount_client = confidential_data_hub_ttrpc_async::SecureMountServiceClient::new(client.clone()); let get_resource_client = @@ -56,6 +65,7 @@ impl CDHClient { sealed_secret_client, secure_mount_client, get_resource_client, + image_pull_client, }) } @@ -111,6 +121,24 @@ impl CDHClient { .await?; Ok(res.Resource) } + + pub async fn pull_image(&self, image: &str, bundle_path: &str) -> Result<()> { + let req = confidential_data_hub::ImagePullRequest { + image_url: image.to_string(), + bundle_path: bundle_path.to_string(), + ..Default::default() + }; + + let _ = self + .image_pull_client + .pull_image( + ttrpc::context::with_timeout(AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64), + &req, + ) + .await?; + + Ok(()) + } } pub async fn init_cdh_client(cdh_socket_uri: &str) -> Result<()> { @@ -119,6 +147,7 @@ pub async fn init_cdh_client(cdh_socket_uri: &str) -> Result<()> { CDHClient::new(cdh_socket_uri).context("Failed to create CDH Client") }) .await?; + Ok(()) } @@ -143,6 +172,29 @@ pub async fn unseal_env(env: &str) -> Result { Ok((*env.to_owned()).to_string()) } +/// pull_image is used for call confidential data hub to pull image in the guest. +/// Image layers will store at [`image::KATA_IMAGE_WORK_DIR`]`, +/// rootfs and config.json will store under given `bundle_path`. +/// +/// # Parameters +/// - `image`: Image name (exp: quay.io/prometheus/busybox:latest) +/// - `bundle_path`: The path to store the image bundle (exp. /run/kata-containers/cb0b47276ea66ee9f44cc53afa94d7980b57a52c3f306f68cb034e58d9fbd3c6/rootfs) +pub async fn pull_image(image: &str, bundle_path: PathBuf) -> Result { + fs::create_dir_all(&bundle_path)?; + info!(sl(), "pull image {image:?}, bundle path {bundle_path:?}"); + + let cdh_client = CDH_CLIENT + .get() + .expect("Confidential Data Hub not initialized"); + + cdh_client + .pull_image(image, bundle_path.to_string_lossy().as_ref()) + .await?; + + let image_bundle_path = scoped_join(&bundle_path, "rootfs")?; + Ok(image_bundle_path.as_path().display().to_string()) +} + pub async fn unseal_file(path: &str) -> Result<()> { let cdh_client = CDH_CLIENT .get() @@ -211,7 +263,6 @@ pub async fn unseal_file(path: &str) -> Result<()> { Ok(()) } -#[cfg(feature = "guest-pull")] pub async fn secure_mount( volume_type: &str, options: &std::collections::HashMap, @@ -262,6 +313,18 @@ mod tests { } } + #[async_trait] + impl confidential_data_hub_ttrpc_async::ImagePullService for TestService { + async fn pull_image( + &self, + _ctx: &::ttrpc::asynchronous::TtrpcContext, + _req: confidential_data_hub::ImagePullRequest, + ) -> ttrpc::error::Result { + let output = confidential_data_hub::ImagePullResponse::new(); + Ok(output) + } + } + fn remove_if_sock_exist(sock_addr: &str) -> std::io::Result<()> { let path = sock_addr .strip_prefix("unix://") From f67f5c2b69ab0570bbb4f6705a0bad3cc8445ef5 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:16:10 +0800 Subject: [PATCH 04/17] agent: remove image pull configs As image pull ability is moved to CDH, kata-agent does not need the confugurations of image pulling anymore. All these configurations reading from kernel cmdline is now implemented by CDH. Signed-off-by: Xynnn007 --- src/agent/src/confidential_data_hub/mod.rs | 1 - src/agent/src/config.rs | 114 --------------------- 2 files changed, 115 deletions(-) diff --git a/src/agent/src/confidential_data_hub/mod.rs b/src/agent/src/confidential_data_hub/mod.rs index 3cb48133ce..cf03465e8d 100644 --- a/src/agent/src/confidential_data_hub/mod.rs +++ b/src/agent/src/confidential_data_hub/mod.rs @@ -83,7 +83,6 @@ impl CDHClient { Ok(unsealed_secret.plaintext) } - #[cfg(feature = "guest-pull")] pub async fn secure_mount( &self, volume_type: &str, diff --git a/src/agent/src/config.rs b/src/agent/src/config.rs index c124d6015d..1b64768013 100644 --- a/src/agent/src/config.rs +++ b/src/agent/src/config.rs @@ -32,16 +32,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"; 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"; @@ -147,13 +139,7 @@ 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, pub secure_storage_integrity: bool, - #[cfg(feature = "guest-pull")] - pub enable_signature_verification: bool, - #[cfg(feature = "guest-pull")] - pub image_policy_file: String, #[cfg(feature = "agent-policy")] pub policy_file: String, pub mem_agent: Option, @@ -184,13 +170,7 @@ 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, pub secure_storage_integrity: Option, - #[cfg(feature = "guest-pull")] - pub enable_signature_verification: Option, - #[cfg(feature = "guest-pull")] - pub image_policy_file: Option, #[cfg(feature = "agent-policy")] pub policy_file: Option, pub mem_agent_enable: Option, @@ -284,13 +264,7 @@ 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(""), secure_storage_integrity: false, - #[cfg(feature = "guest-pull")] - enable_signature_verification: false, - #[cfg(feature = "guest-pull")] - image_policy_file: String::from(""), #[cfg(feature = "agent-policy")] policy_file: String::from(""), mem_agent: None, @@ -333,16 +307,6 @@ 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); - 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); #[cfg(feature = "agent-policy")] @@ -557,27 +521,6 @@ 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 - ); - 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, @@ -901,11 +844,6 @@ 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] @@ -931,13 +869,7 @@ mod tests { no_proxy: &'a str, guest_components_rest_api: GuestComponentsFeatures, guest_components_procs: GuestComponentsProcs, - #[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, #[cfg(feature = "agent-policy")] policy_file: &'a str, mem_agent: Option, @@ -961,13 +893,7 @@ mod tests { no_proxy: "", guest_components_rest_api: GuestComponentsFeatures::default(), guest_components_procs: GuestComponentsProcs::default(), - #[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: "", #[cfg(feature = "agent-policy")] policy_file: "", mem_agent: None, @@ -1418,18 +1344,6 @@ 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() - }, TestData { contents: "", secure_storage_integrity: false, @@ -1455,24 +1369,6 @@ 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() - }, #[cfg(feature = "agent-policy")] // Test environment TestData { @@ -1575,16 +1471,6 @@ mod tests { "{}", msg ); - #[cfg(feature = "guest-pull")] - { - 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, "{}", From 39cd43099456816d1497e93e98ef7c698e1b97b6 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:17:25 +0800 Subject: [PATCH 05/17] agent: add ocicrypt_config envs for CDH process now image pull ability is moved to CDH, thus the CDH process needs environment variables of ocicrypt to help find the keyprovider(cdh) to decrypt images. Signed-off-by: Xynnn007 --- src/agent/src/main.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index 081f14e73c..7f43b59d03 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -391,9 +391,6 @@ async fn start_sandbox( s.rtnl.handle_localhost().await?; } - #[cfg(feature = "guest-pull")] - confidential_data_hub::image::set_proxy_env_vars().await; - #[cfg(feature = "agent-policy")] if let Err(e) = initialize_policy().await { error!(logger, "Failed to initialize agent policy: {:?}", e); @@ -513,6 +510,7 @@ async fn launch_guest_component_procs( Some(AA_CONFIG_PATH), AA_ATTESTATION_SOCKET, DEFAULT_LAUNCH_PROCESS_TIMEOUT, + &[], ) .await .map_err(|e| anyhow!("launch_process {} failed: {:?}", AA_PATH, e))?; @@ -534,6 +532,7 @@ async fn launch_guest_component_procs( Some(CDH_CONFIG_PATH), CDH_SOCKET, DEFAULT_LAUNCH_PROCESS_TIMEOUT, + &[("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH)], ) .await .map_err(|e| anyhow!("launch_process {} failed: {:?}", CDH_PATH, e))?; @@ -555,6 +554,7 @@ async fn launch_guest_component_procs( None, "", 0, + &[], ) .await .map_err(|e| anyhow!("launch_process {} failed: {:?}", API_SERVER_PATH, e))?; @@ -578,8 +578,6 @@ async fn init_attestation_components( Ok(md) => { if md.file_type().is_socket() { confidential_data_hub::init_cdh_client(CDH_SOCKET_URI).await?; - fs::write(OCICRYPT_CONFIG_PATH, OCICRYPT_CONFIG.as_bytes())?; - env::set_var("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH); } else { debug!(logger, "File {} is not a socket", CDH_SOCKET); } @@ -621,6 +619,7 @@ async fn launch_process( config: Option<&str>, unix_socket_path: &str, timeout_secs: i32, + envs: &[(&str, &str)], ) -> Result<()> { if !Path::new(path).exists() { bail!("path {} does not exist.", path); @@ -637,7 +636,12 @@ async fn launch_process( tokio::fs::remove_file(unix_socket_path).await?; } - tokio::process::Command::new(path).args(args).spawn()?; + let mut process = tokio::process::Command::new(path); + process.args(args); + for (k, v) in envs { + process.env(k, v); + } + process.spawn()?; if !unix_socket_path.is_empty() && timeout_secs > 0 { wait_for_path_to_exist(logger, unix_socket_path, timeout_secs).await?; } From 22c50cae7bd678307e720be20d0b508a36e8160e Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:19:11 +0800 Subject: [PATCH 06/17] agent: let image_pull_handler call cdh to pull image This is a higher level calling to pull image inside guest. Now it should call confidential_data_hub's API. As the previous pull_image API does 1. check is sandbox 2. generate bundle_path inside the original logic, and the new API does not do them to keep the API semantice clean, thus before we call the API, we explicitly do the two things. Signed-off-by: Xynnn007 --- src/agent/src/storage/image_pull_handler.rs | 35 +++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/agent/src/storage/image_pull_handler.rs b/src/agent/src/storage/image_pull_handler.rs index 4ed011d3d8..74686abf43 100644 --- a/src/agent/src/storage/image_pull_handler.rs +++ b/src/agent/src/storage/image_pull_handler.rs @@ -4,12 +4,15 @@ // use super::new_device; -use crate::image; +use crate::confidential_data_hub; +use crate::confidential_data_hub::image::{is_sandbox, unpack_pause_image}; +use crate::rpc::CONTAINER_BASE; use crate::storage::{StorageContext, StorageHandler}; use anyhow::{anyhow, Result}; use kata_types::mount::KATA_VIRTUAL_VOLUME_IMAGE_GUEST_PULL; use kata_types::mount::{ImagePullVolume, StorageDevice}; use protocols::agent::Storage; +use safe_path::scoped_join; use std::sync::Arc; use tracing::instrument; @@ -53,7 +56,35 @@ impl StorageHandler for ImagePullHandler { .cid .clone() .ok_or_else(|| anyhow!("failed to get container id"))?; - let bundle_path = image::pull_image(image_name, &cid, &image_pull_volume.metadata).await?; + + info!( + ctx.logger, + "image metadata: {:?}", image_pull_volume.metadata + ); + if is_sandbox(&image_pull_volume.metadata) { + let mount_path = unpack_pause_image(&cid)?; + return new_device(mount_path); + } + + // generated bundles with rootfs and config.json will store under CONTAINER_BASE/cid/images. + let bundle_path = scoped_join(CONTAINER_BASE, &cid)?; + let bundle_path = match confidential_data_hub::pull_image(image_name, bundle_path).await { + Ok(path) => { + info!( + ctx.logger, + "pull and unpack image {image_name}, cid: {cid} succeeded." + ); + path + } + Err(e) => { + error!( + ctx.logger, + "pull and unpack image {image_name}, cid: {cid} failed with {:?}.", + e.to_string() + ); + return Err(e); + } + }; new_device(bundle_path) } From 0e15b49369eb6dc1d1f6f23fb4dadda4797eb16a Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:23:36 +0800 Subject: [PATCH 07/17] agent: get rid of init_image_service we do not need to initialize image service in kata-agent now, as it's initialized in CDH. Signed-off-by: Xynnn007 --- src/agent/src/rpc.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 278cc947ad..1ebdb87d0c 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -1328,10 +1328,6 @@ impl agent_ttrpc::AgentService for AgentService { s.network.set_dns(dns); } } - #[cfg(feature = "guest-pull")] - confidential_data_hub::image::init_image_service() - .await - .map_ttrpc_err(same)?; Ok(Empty::new()) } From 22e65024ce30b601ab95a99b0508193c593fb945 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:25:05 +0800 Subject: [PATCH 08/17] agent: get rid of pull-type option The feature `guest-pull` and `default-pull` are both removed, because both guest pull and host pull are supported in building time without without involving new dependencies like image-rs before. The guest pull will depend on the CDH process, not the build time feature. Signed-off-by: Xynnn007 --- src/agent/Makefile | 10 ---------- src/agent/src/features.rs | 2 -- src/agent/src/rpc.rs | 5 ----- src/agent/src/storage/mod.rs | 3 --- 4 files changed, 20 deletions(-) diff --git a/src/agent/Makefile b/src/agent/Makefile index 2e51c3a117..0fed742b9b 100644 --- a/src/agent/Makefile +++ b/src/agent/Makefile @@ -41,16 +41,6 @@ ifeq ($(AGENT_POLICY),yes) override EXTRA_RUSTFEATURES += agent-policy endif -##VAR PULL_TYPE=default|guest-pull define if agent enables the guest pull image feature -PULL_TYPE ?= default -ifeq ($(PULL_TYPE),default) - override EXTRA_RUSTFEATURES += default-pull -# Enable guest pull image feature of rust build -else ifeq ($(PULL_TYPE),guest-pull) - override EXTRA_RUSTFEATURES += guest-pull -endif - - include ../../utils.mk ##VAR STANDARD_OCI_RUNTIME=yes|no define if agent enables standard oci runtime feature diff --git a/src/agent/src/features.rs b/src/agent/src/features.rs index 3c06d8cef8..c5f1b00e28 100644 --- a/src/agent/src/features.rs +++ b/src/agent/src/features.rs @@ -8,8 +8,6 @@ pub fn get_build_features() -> Vec { let features: Vec<&str> = vec![ #[cfg(feature = "agent-policy")] "agent-policy", - #[cfg(feature = "guest-pull")] - "guest-pull", #[cfg(feature = "seccomp")] "seccomp", #[cfg(feature = "standard-oci-runtime")] diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 1ebdb87d0c..f072434f2e 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -57,7 +57,6 @@ use rustjail::process::ProcessOperations; #[cfg(target_arch = "s390x")] use crate::ccw; -#[cfg(feature = "guest-pull")] use crate::confidential_data_hub::image::KATA_IMAGE_WORK_DIR; use crate::device::block_device_handler::get_virtio_blk_pci_device_name; #[cfg(target_arch = "s390x")] @@ -108,7 +107,6 @@ use kata_types::k8s; pub const CONTAINER_BASE: &str = "/run/kata-containers"; const MODPROBE_PATH: &str = "/sbin/modprobe"; -#[cfg(feature = "guest-pull")] const TRUSTED_IMAGE_STORAGE_DEVICE: &str = "/dev/trusted_store"; /// the iptables seriers binaries could appear either in /sbin /// or /usr/sbin, we need to check both of them @@ -238,7 +236,6 @@ impl AgentService { handle_cdi_devices(&sl(), &mut oci, "/var/run/cdi", AGENT_CONFIG.cdi_timeout).await?; // Handle trusted storage configuration before mounting any storage - #[cfg(feature = "guest-pull")] cdh_handler_trusted_storage(&mut oci) .await .map_err(|e| anyhow!("failed to handle trusted storage: {}", e))?; @@ -316,14 +313,12 @@ impl AgentService { let pipe_size = AGENT_CONFIG.container_pipe_size; let p = if let Some(p) = oci.process() { - #[cfg(feature = "guest-pull")] { let new_p = confidential_data_hub::image::get_process(p, &oci, req.storages.clone())?; Process::new(&sl(), &new_p, cid.as_str(), true, pipe_size, proc_io)? } - #[cfg(not(feature = "guest-pull"))] Process::new(&sl(), p, cid.as_str(), true, pipe_size, proc_io)? } else { info!(sl(), "no process configurations!"); diff --git a/src/agent/src/storage/mod.rs b/src/agent/src/storage/mod.rs index 3b18f345e0..237ca4417b 100644 --- a/src/agent/src/storage/mod.rs +++ b/src/agent/src/storage/mod.rs @@ -24,7 +24,6 @@ use self::bind_watcher_handler::BindWatcherHandler; use self::block_handler::{PmemHandler, ScsiHandler, VirtioBlkMmioHandler, VirtioBlkPciHandler}; use self::ephemeral_handler::EphemeralHandler; use self::fs_handler::{OverlayfsHandler, Virtio9pHandler, VirtioFsHandler}; -#[cfg(feature = "guest-pull")] use self::image_pull_handler::ImagePullHandler; use self::local_handler::LocalHandler; use crate::mount::{baremount, is_mounted, remove_mounts}; @@ -36,7 +35,6 @@ mod bind_watcher_handler; mod block_handler; mod ephemeral_handler; mod fs_handler; -#[cfg(feature = "guest-pull")] mod image_pull_handler; mod local_handler; @@ -148,7 +146,6 @@ lazy_static! { Arc::new(BindWatcherHandler {}), #[cfg(target_arch = "s390x")] Arc::new(self::block_handler::VirtioBlkCcwHandler {}), - #[cfg(feature = "guest-pull")] Arc::new(ImagePullHandler {}), ]; From 6b1249186f96180ff3d33f96c68e7728a84348fb Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:27:15 +0800 Subject: [PATCH 09/17] agent: embed ocicrypt config in rootfs by default Now the ocicrypt configuration used by CDH is always the same and it's not a good practics to write it into the rootfs during runtime by kata-agent. Thus we now move it to coco-guest-components build script. The config will be embedded into guest image/initrd together with CDH binary. Signed-off-by: Xynnn007 --- src/agent/src/main.rs | 18 ++++-------------- .../build-static-coco-guest-components.sh | 1 + 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index 7f43b59d03..13c48f4104 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -22,7 +22,7 @@ use anyhow::{anyhow, bail, Context, Result}; use base64::Engine; use cfg_if::cfg_if; use clap::{AppSettings, Parser}; -use const_format::{concatcp, formatcp}; +use const_format::concatcp; use initdata::{InitdataReturnValue, AA_CONFIG_PATH, CDH_CONFIG_PATH}; use nix::fcntl::OFlag; use nix::sys::reboot::{reboot, RebootMode}; @@ -107,19 +107,9 @@ const CDH_SOCKET_URI: &str = concatcp!(UNIX_SOCKET_PREFIX, CDH_SOCKET); const API_SERVER_PATH: &str = "/usr/local/bin/api-server-rest"; -/// Path of ocicrypt config file. This is used by image-rs when decrypting image. -const OCICRYPT_CONFIG_PATH: &str = "/run/confidential-containers/ocicrypt_config.json"; - -const OCICRYPT_CONFIG: &str = formatcp!( - r#"{{ - "key-providers": {{ - "attestation-agent": {{ - "ttrpc": "{}" - }} - }} -}}"#, - CDH_SOCKET_URI -); +/// Path of ocicrypt config file. This is used by CDH when decrypting image. +/// TODO: remove this when we move the launch of CDH out of the kata-agent. +const OCICRYPT_CONFIG_PATH: &str = "/etc/ocicrypt_config.json"; const DEFAULT_LAUNCH_PROCESS_TIMEOUT: i32 = 6; diff --git a/tools/packaging/static-build/coco-guest-components/build-static-coco-guest-components.sh b/tools/packaging/static-build/coco-guest-components/build-static-coco-guest-components.sh index 669773a5b9..6eaf925ee4 100755 --- a/tools/packaging/static-build/coco-guest-components/build-static-coco-guest-components.sh +++ b/tools/packaging/static-build/coco-guest-components/build-static-coco-guest-components.sh @@ -35,6 +35,7 @@ build_coco_guest_components_from_source() { DESTDIR="${DESTDIR}/usr/local/bin" TEE_PLATFORM=${TEE_PLATFORM} make install install -D -m0755 "confidential-data-hub/hub/src/storage/scripts/luks-encrypt-storage" "${DESTDIR}/usr/local/bin/luks-encrypt-storage" + install -D -m0644 "confidential-data-hub/hub/src/image/ocicrypt_config.json" "${DESTDIR}/etc/ocicrypt_config.json" popd } From 105cb479917f4fca5e0484466e94b66860a515cf Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 13 Jun 2025 10:39:33 +0800 Subject: [PATCH 10/17] agent: always try to override oci process spec In previous version, only when the `guest-pull` feature is enabled during the build time, the OCI process will be tried to be overrided when the storage has a guest pull volume and also it is sandbox. After getting rid of the feature, whether it is guest-pull is runtimely determined thus we can always do this trying override, by checking if there is kata guest pull volume in storages and it's sandbox. Signed-off-by: Xynnn007 --- src/agent/src/rpc.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index f072434f2e..3bcdf54420 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -312,19 +312,14 @@ impl AgentService { let pipe_size = AGENT_CONFIG.container_pipe_size; - let p = if let Some(p) = oci.process() { - { - let new_p = - confidential_data_hub::image::get_process(p, &oci, req.storages.clone())?; - Process::new(&sl(), &new_p, cid.as_str(), true, pipe_size, proc_io)? - } - - Process::new(&sl(), p, cid.as_str(), true, pipe_size, proc_io)? - } else { + let Some(p) = oci.process() else { info!(sl(), "no process configurations!"); return Err(anyhow!(nix::Error::EINVAL)); }; + let new_p = confidential_data_hub::image::get_process(p, &oci, req.storages.clone())?; + let p = Process::new(&sl(), &new_p, cid.as_str(), true, pipe_size, proc_io)?; + // if starting container failed, we will do some rollback work // to ensure no resources are leaked. if let Err(err) = ctr.start(p).await { From 44a6d1a6f7811793bcf8c1c97e5d1b10f8515c2b Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Sun, 27 Apr 2025 13:48:07 +0800 Subject: [PATCH 11/17] docs: update guest pull document After moving guest pull abilities to CDH, the document of guest pull should be updated due to new workflow. Also, replace the diagram of PNG into a mermaid one for better maintaince. Signed-off-by: Xynnn007 --- .../guest-image-management-architecture.png | Bin 62825 -> 0 bytes .../guest-image-management-details.png | Bin 125267 -> 0 bytes .../kata-guest-image-management-design.md | 59 +++++++++++++++--- 3 files changed, 52 insertions(+), 7 deletions(-) delete mode 100644 docs/design/arch-images/guest-image-management-architecture.png delete mode 100644 docs/design/arch-images/guest-image-management-details.png diff --git a/docs/design/arch-images/guest-image-management-architecture.png b/docs/design/arch-images/guest-image-management-architecture.png deleted file mode 100644 index 83ab0f022c5801556634b2082e85b687fd63e370..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62825 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ɦ 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 C_%XHs diff --git a/docs/design/arch-images/guest-image-management-details.png b/docs/design/arch-images/guest-image-management-details.png deleted file mode 100644 index d58afe71a57b163ee5d0088c3114f8d993f60041..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125267 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 |1\. Pull image request & metadata|Containerd + Containerd-->|2\. Pull image metadata| E + Containerd-->Snapshotter[Nydus Snapshotter] + Snapshotter-->|3\. Pack image info| Containerd + Containerd-->Runtime[Kata Runtime] + Runtime-->Hypervisor + Hypervisor-->TEE + Runtime-->|4\. Pass image info to VM| Agent + CDH1-->|6\. Pull image with image info|E[Container Images Registry] + subgraph TEE [Virtual Machine] + Images[Container Images]-->|7\. Prepare container rootfs|H[Container] + + subgraph CDH [Confidential Data Hub] + CDH1[Image Mgmt] + end + + CDH-->Images + Agent[Kata Agent]-->|5\. Call image pull RPC|CDH + end +``` #### Sequence diagrams The following sequence diagram depicted below offers a detailed overview of the messages/calls exchanged to pull an unencrypted unsigned image from an unauthenticated container registry. This involves the kata-runtime, kata-agent, and the guest-components’ image-rs to use the guest pull mechanism. -![guest-image-management-details](arch-images/guest-image-management-details.png) +```mermaid +sequenceDiagram + par Hosts Side + Containerd/Kubelet->>runtime.kata_agent: createContainer(ctx,sandbox,c) + runtime.kata_agent->>runtime.fs_share_linux: ShareRootFilesystem(ctx,c) + runtime.fs_share_linux->>runtime.kata_agent: handleVirtualVolumeStorageObject(c,...,KataVolumeType) + runtime.kata_agent->>runtime.kata_agent: handleImageGuestPullBlockVolume(c,virtVolume,vol) + runtime.kata_agent->>runtime.fs_share_linux: ret:storage + runtime.fs_share_linux->>runtime.kata_agent: ret:sharedFile + and Guest Side + runtime.kata_agent->>agent.rpc: CreateContainerRequest(cid,...,storages,...,oci,...) + agent.rpc->>agent.storage: add_storage(storages...) + agent.storage->>agent.storage: StorageHandler.handler(driver) + agent.storage->>agent.storage.StorageHandler.ImagePullHandler: create_device(storage) + agent.storage.StorageHandler.ImagePullHandler->>agent.confidential_data_hub: pull_image(img,cid,img_metadata) + agent.confidential_data_hub->>Confidential Data Hub: pull_image(img,bundle_path) + Confidential Data Hub->>agent.confidential_data_hub: ret + agent.confidential_data_hub->>agent.storage.StorageHandler.ImagePullHandler: ret: bundle_path + agent.storage.StorageHandler.ImagePullHandler->>agent.storage: ret: device + agent.storage->>agent.rpc: ret: mount_list + and Return + agent.rpc->>runtime.kata_agent: ret: ok + runtime.kata_agent->>Containerd/Kubelet: ret: ok + end +``` First and foremost, the guest pull code path is only activated when `nydus snapshotter` requires the handling of a volume which type is `image_guest_pull`, as can be seen on the message below: ```json @@ -108,10 +153,10 @@ Below is an example of storage information packaged in the message sent to the k ``` Next, the kata-agent's RPC module will handle the create container request which, among other things, involves adding storages to the sandbox. The storage module contains implementations of `StorageHandler` interface for various storage types, being the `ImagePullHandler` in charge of handling the storage object for the container image (the storage manager instantiates the handler based on the value of the "driver"). -`ImagePullHandler` delegates the image pulling operation to the `ImageService.pull_image()` that is going to create the image's bundle directory on the guest filesystem and, in turn, class the image-rs to in fact fetch and uncompress the image's bundle. +`ImagePullHandler` delegates the image pulling operation to the `confidential_data_hub.pull_image()` that is going to create the image's bundle directory on the guest filesystem and, in turn, the `ImagePullService` of Confidential Data Hub to fetch, uncompress and mount the image's rootfs. > **Notes:** -> In this flow, `ImageService.pull_image()` parses the image metadata, looking for either the `io.kubernetes.cri.container-type: sandbox` or `io.kubernetes.cri-o.ContainerType: sandbox` (CRI-IO case) annotation, then it never calls the `image-rs.pull_image()` because the pause image is expected to already be inside the guest's filesystem, so instead `ImageService.unpack_pause_image()` is called. +> In this flow, `confidential_data_hub.pull_image()` parses the image metadata, looking for either the `io.kubernetes.cri.container-type: sandbox` or `io.kubernetes.cri-o.ContainerType: sandbox` (CRI-IO case) annotation, then it never calls the `pull_image()` RPC of Confidential Data Hub because the pause image is expected to already be inside the guest's filesystem, so instead `confidential_data_hub.unpack_pause_image()` is called. ## Using guest image pull with `nerdctl` @@ -121,6 +166,6 @@ nerdctl run --runtime io.containerd.kata.v2 --snapshotter nydus --label io.kuber ``` References: -[1] [[RFC] Image management proposal for hosting sharing and peer pods](https://github.com/confidential-containers/confidential-containers/issues/137) -[2] https://github.com/containerd/containerd/blob/main/docs/content-flow.md - +1. [[RFC] Image management proposal for hosting sharing and peer pods](https://github.com/confidential-containers/confidential-containers/issues/137) +2. https://github.com/containerd/containerd/blob/main/docs/content-flow.md +3. [Move guest pull ability to a configurable component](https://github.com/kata-containers/kata-containers/issues/9266) From 7420194ea8f7b7a7487cb2d3d354355d65652b0b Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Sun, 27 Apr 2025 14:13:22 +0800 Subject: [PATCH 12/17] build: abandon PULL_TYPE build env Now kata-agent by default supports both guest pull and host pull abilities, thus we do not need to specify the PULL_TYPE env when building kata-agent. Signed-off-by: Xynnn007 --- tools/osbuilder/rootfs-builder/rootfs.sh | 4 +--- tools/packaging/guest-image/build_image.sh | 2 -- .../local-build/kata-deploy-binaries-in-docker.sh | 2 -- .../kata-deploy/local-build/kata-deploy-binaries.sh | 5 +---- tools/packaging/static-build/agent/build-static-agent.sh | 4 ++-- tools/packaging/static-build/agent/build.sh | 1 - 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/tools/osbuilder/rootfs-builder/rootfs.sh b/tools/osbuilder/rootfs-builder/rootfs.sh index 0a79c21bfa..9331c143e5 100755 --- a/tools/osbuilder/rootfs-builder/rootfs.sh +++ b/tools/osbuilder/rootfs-builder/rootfs.sh @@ -17,8 +17,6 @@ RUST_VERSION="null" AGENT_BIN=${AGENT_BIN:-kata-agent} AGENT_INIT=${AGENT_INIT:-no} MEASURED_ROOTFS=${MEASURED_ROOTFS:-no} -# The kata agent enables guest-pull feature. -PULL_TYPE=${PULL_TYPE:-default} KERNEL_MODULES_DIR=${KERNEL_MODULES_DIR:-""} OSBUILDER_VERSION="unknown" DOCKER_RUNTIME=${DOCKER_RUNTIME:-runc} @@ -747,7 +745,7 @@ EOF git checkout "${AGENT_VERSION}" && OK "git checkout successful" || die "checkout agent ${AGENT_VERSION} failed!" fi make clean - make LIBC=${LIBC} INIT=${AGENT_INIT} SECCOMP=${SECCOMP} AGENT_POLICY=${AGENT_POLICY} PULL_TYPE=${PULL_TYPE} + make LIBC=${LIBC} INIT=${AGENT_INIT} SECCOMP=${SECCOMP} AGENT_POLICY=${AGENT_POLICY} make install DESTDIR="${ROOTFS_DIR}" LIBC=${LIBC} INIT=${AGENT_INIT} if [ "${SECCOMP}" == "yes" ]; then rm -rf "${libseccomp_install_dir}" "${gperf_install_dir}" diff --git a/tools/packaging/guest-image/build_image.sh b/tools/packaging/guest-image/build_image.sh index 228b3e1c17..b0f896c7b7 100755 --- a/tools/packaging/guest-image/build_image.sh +++ b/tools/packaging/guest-image/build_image.sh @@ -47,7 +47,6 @@ build_initrd() { AGENT_TARBALL="${AGENT_TARBALL}" \ AGENT_INIT="${AGENT_INIT:-no}" \ AGENT_POLICY="${AGENT_POLICY:-}" \ - PULL_TYPE="${PULL_TYPE:-default}" \ COCO_GUEST_COMPONENTS_TARBALL="${COCO_GUEST_COMPONENTS_TARBALL:-}" \ PAUSE_IMAGE_TARBALL="${PAUSE_IMAGE_TARBALL:-}" \ GUEST_HOOKS_TARBALL="${GUEST_HOOKS_TARBALL}" @@ -77,7 +76,6 @@ build_image() { ROOTFS_BUILD_DEST="${builddir}/rootfs-image" \ AGENT_TARBALL="${AGENT_TARBALL}" \ AGENT_POLICY="${AGENT_POLICY:-}" \ - PULL_TYPE="${PULL_TYPE:-default}" \ COCO_GUEST_COMPONENTS_TARBALL="${COCO_GUEST_COMPONENTS_TARBALL:-}" \ PAUSE_IMAGE_TARBALL="${PAUSE_IMAGE_TARBALL:-}" \ GUEST_HOOKS_TARBALL="${GUEST_HOOKS_TARBALL}" diff --git a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh index 56a1f44d6c..fc3e8ca8e8 100755 --- a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh +++ b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh @@ -100,7 +100,6 @@ TOOLS_CONTAINER_BUILDER="${TOOLS_CONTAINER_BUILDER:-}" VIRTIOFSD_CONTAINER_BUILDER="${VIRTIOFSD_CONTAINER_BUILDER:-}" AGENT_INIT="${AGENT_INIT:-no}" MEASURED_ROOTFS="${MEASURED_ROOTFS:-}" -PULL_TYPE="${PULL_TYPE:-guest-pull}" USE_CACHE="${USE_CACHE:-}" BUSYBOX_CONF_FILE=${BUSYBOX_CONF_FILE:-} NVIDIA_GPU_STACK="${NVIDIA_GPU_STACK:-}" @@ -140,7 +139,6 @@ docker run \ --env VIRTIOFSD_CONTAINER_BUILDER="${VIRTIOFSD_CONTAINER_BUILDER}" \ --env AGENT_INIT="${AGENT_INIT}" \ --env MEASURED_ROOTFS="${MEASURED_ROOTFS}" \ - --env PULL_TYPE="${PULL_TYPE}" \ --env USE_CACHE="${USE_CACHE}" \ --env BUSYBOX_CONF_FILE="${BUSYBOX_CONF_FILE}" \ --env NVIDIA_GPU_STACK="${NVIDIA_GPU_STACK}" \ diff --git a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh index d0c3394902..902497481f 100755 --- a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh +++ b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh @@ -43,7 +43,6 @@ readonly se_image_builder="${repo_root_dir}/tools/packaging/guest-image/build_se ARCH=${ARCH:-$(uname -m)} BUSYBOX_CONF_FILE="${BUSYBOX_CONF_FILE:-}" MEASURED_ROOTFS=${MEASURED_ROOTFS:-no} -PULL_TYPE=${PULL_TYPE:-guest-pull} USE_CACHE="${USE_CACHE:-"yes"}" ARTEFACT_REGISTRY="${ARTEFACT_REGISTRY:-ghcr.io}" ARTEFACT_REPOSITORY="${ARTEFACT_REPOSITORY:-kata-containers}" @@ -430,7 +429,6 @@ install_image_confidential() { else export MEASURED_ROOTFS=yes fi - export PULL_TYPE=default install_image "confidential" } @@ -529,7 +527,6 @@ install_initrd() { #Install guest initrd for confidential guests install_initrd_confidential() { export MEASURED_ROOTFS=no - export PULL_TYPE=default install_initrd "confidential" } @@ -997,7 +994,7 @@ install_agent() { export GPERF_URL="$(get_from_kata_deps ".externals.gperf.url")" info "build static agent" - DESTDIR="${destdir}" AGENT_POLICY="${AGENT_POLICY}" PULL_TYPE=${PULL_TYPE} "${agent_builder}" + DESTDIR="${destdir}" AGENT_POLICY="${AGENT_POLICY}" "${agent_builder}" } install_coco_guest_components() { diff --git a/tools/packaging/static-build/agent/build-static-agent.sh b/tools/packaging/static-build/agent/build-static-agent.sh index e57af1ad6c..b2aa45ecb4 100755 --- a/tools/packaging/static-build/agent/build-static-agent.sh +++ b/tools/packaging/static-build/agent/build-static-agent.sh @@ -18,8 +18,8 @@ build_agent_from_source() { /usr/bin/install_libseccomp.sh /opt /opt cd src/agent - DESTDIR=${DESTDIR} AGENT_POLICY=${AGENT_POLICY} PULL_TYPE=${PULL_TYPE} make - DESTDIR=${DESTDIR} AGENT_POLICY=${AGENT_POLICY} PULL_TYPE=${PULL_TYPE} make install + DESTDIR=${DESTDIR} AGENT_POLICY=${AGENT_POLICY} make + DESTDIR=${DESTDIR} AGENT_POLICY=${AGENT_POLICY} make install } build_agent_from_source "$@" diff --git a/tools/packaging/static-build/agent/build.sh b/tools/packaging/static-build/agent/build.sh index 6482b9680c..c9ea6b83f4 100755 --- a/tools/packaging/static-build/agent/build.sh +++ b/tools/packaging/static-build/agent/build.sh @@ -26,7 +26,6 @@ docker pull ${container_image} || \ docker run --rm -i -v "${repo_root_dir}:${repo_root_dir}" \ --env DESTDIR=${DESTDIR} \ --env AGENT_POLICY=${AGENT_POLICY:-no} \ - --env PULL_TYPE=${PULL_TYPE:-default} \ --env LIBSECCOMP_VERSION=${LIBSECCOMP_VERSION} \ --env LIBSECCOMP_URL=${LIBSECCOMP_URL} \ --env GPERF_VERSION=${GPERF_VERSION} \ From 93826ff90cd32b6b13bfe4706971f4eb901b3200 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 9 May 2025 17:28:35 +0800 Subject: [PATCH 13/17] tests: update negative test log assertions After moving image pulling from kata-agent to CDH, the failed image pull error messages have been slightly changed. This commit is to apply for the change. Note that in original and current image-rs implementation, both no key or wrong key will result in a same error information. Signed-off-by: Xynnn007 --- .../kubernetes/k8s-guest-pull-image-authenticated.bats | 4 ++-- .../kubernetes/k8s-guest-pull-image-encrypted.bats | 5 ++--- .../kubernetes/k8s-guest-pull-image-signature.bats | 4 ++-- tests/integration/kubernetes/k8s-initdata.bats | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/integration/kubernetes/k8s-guest-pull-image-authenticated.bats b/tests/integration/kubernetes/k8s-guest-pull-image-authenticated.bats index 27b71dbdb4..3dd2cdbbd4 100644 --- a/tests/integration/kubernetes/k8s-guest-pull-image-authenticated.bats +++ b/tests/integration/kubernetes/k8s-guest-pull-image-authenticated.bats @@ -87,7 +87,7 @@ function setup_kbs_credentials() { echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull image" + assert_logs_contain "${node}" kata "${node_start_time}" "Not authorized" } @test "Test that creating a container from an authenticated image, with no credentials fails" { @@ -100,7 +100,7 @@ function setup_kbs_credentials() { echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull image" + assert_logs_contain "${node}" kata "${node_start_time}" "Not authorized" } teardown() { diff --git a/tests/integration/kubernetes/k8s-guest-pull-image-encrypted.bats b/tests/integration/kubernetes/k8s-guest-pull-image-encrypted.bats index 564769bf31..a398766838 100644 --- a/tests/integration/kubernetes/k8s-guest-pull-image-encrypted.bats +++ b/tests/integration/kubernetes/k8s-guest-pull-image-encrypted.bats @@ -52,8 +52,7 @@ function setup_kbs_decryption_key() { echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" 'decrypt image (unwrap key) failed' - assert_logs_contain "${node}" kata "${node_start_time}" 'kms interface when get KEK failed' + assert_logs_contain "${node}" kata "${node_start_time}" 'Failed to decrypt the image layer, please ensure that the decryption key is placed and correct' } @@ -80,7 +79,7 @@ function setup_kbs_decryption_key() { echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" 'decrypt image (unwrap key) failed' + assert_logs_contain "${node}" kata "${node_start_time}" 'Failed to decrypt the image layer, please ensure that the decryption key is placed and correct' } teardown() { diff --git a/tests/integration/kubernetes/k8s-guest-pull-image-signature.bats b/tests/integration/kubernetes/k8s-guest-pull-image-signature.bats index 5276e8ec72..8741b107eb 100644 --- a/tests/integration/kubernetes/k8s-guest-pull-image-signature.bats +++ b/tests/integration/kubernetes/k8s-guest-pull-image-signature.bats @@ -97,7 +97,7 @@ EOF echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull image" + 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" { @@ -123,7 +123,7 @@ EOF echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull image" + 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" { diff --git a/tests/integration/kubernetes/k8s-initdata.bats b/tests/integration/kubernetes/k8s-initdata.bats index d98f207471..5921cbdb94 100644 --- a/tests/integration/kubernetes/k8s-initdata.bats +++ b/tests/integration/kubernetes/k8s-initdata.bats @@ -165,7 +165,7 @@ EOF echo "Pod ${kata_pod}: $(cat ${kata_pod})" assert_pod_fail "${kata_pod}" - assert_logs_contain "${node}" kata "${node_start_time}" "failed to pull image" + 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" { From aae64fa3d6dde324d7c494778750011c381df433 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Wed, 14 May 2025 00:06:41 +0800 Subject: [PATCH 14/17] agent: add agent.image_pull_timeout parameter This new parameter for kata-agent is used to control the timeout for a guest pull request. Note that sometimes an image can be really big, so we set default timeout to 1200 seconds (20 minutes). Signed-off-by: Xynnn007 --- src/agent/README.md | 3 ++- src/agent/src/confidential_data_hub/mod.rs | 2 +- src/agent/src/config.rs | 21 ++++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/agent/README.md b/src/agent/README.md index 4309676642..2f291321ee 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_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.hotplug_timeout` | Hotplug timeout | Allow to configure hotplug timeout(seconds) of block devices | integer | `3` | | `agent.cdh_api_timeout` | Confidential Data Hub (CDH) API timeout | Allow to configure CDH API timeout(seconds) | integer | `50` | +| `agent.image_pull_timeout` | Confidential Data Hub (CDH) Image Pull API timeout | Allow to configure CDH API image pull timeout(seconds) | integer | `1200` | | `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 | `""` | @@ -148,7 +149,7 @@ The kata agent has the ability to configure agent options in guest kernel comman > The agent will fail to start if the configuration file is not present, > or if it can't be parsed properly. > - `agent.devmode`: true | false -> - `agent.hotplug_timeout` and `agent.cdh_api_timeout`: a whole number of seconds +> - `agent.hotplug_timeout`, `agent.image_pull_timeout` and `agent.cdh_api_timeout`: a whole number of seconds > - `agent.log`: "critical"("fatal" | "panic") | "error" | "warn"("warning") | "info" | "debug" > - `agent.server_addr`: "{VSOCK_ADDR}:{VSOCK_PORT}" > - `agent.trace`: true | false diff --git a/src/agent/src/confidential_data_hub/mod.rs b/src/agent/src/confidential_data_hub/mod.rs index cf03465e8d..7099251d31 100644 --- a/src/agent/src/confidential_data_hub/mod.rs +++ b/src/agent/src/confidential_data_hub/mod.rs @@ -131,7 +131,7 @@ impl CDHClient { let _ = self .image_pull_client .pull_image( - ttrpc::context::with_timeout(AGENT_CONFIG.cdh_api_timeout.as_nanos() as i64), + ttrpc::context::with_timeout(AGENT_CONFIG.image_pull_timeout.as_nanos() as i64), &req, ) .await?; diff --git a/src/agent/src/config.rs b/src/agent/src/config.rs index 1b64768013..6db42ff91e 100644 --- a/src/agent/src/config.rs +++ b/src/agent/src/config.rs @@ -23,6 +23,7 @@ const SERVER_ADDR_OPTION: &str = "agent.server_addr"; const PASSFD_LISTENER_PORT: &str = "agent.passfd_listener_port"; const HOTPLUG_TIMOUT_OPTION: &str = "agent.hotplug_timeout"; const CDH_API_TIMOUT_OPTION: &str = "agent.cdh_api_timeout"; +const CDH_IMAGE_PULL_TIMEOUT_OPTION: &str = "agent.image_pull_timeout"; const CDI_TIMEOUT_OPTION: &str = "agent.cdi_timeout"; const DEBUG_CONSOLE_VPORT_OPTION: &str = "agent.debug_console_vport"; const LOG_VPORT_OPTION: &str = "agent.log_vport"; @@ -63,6 +64,7 @@ const MEM_AGENT_COMPACT_FORCE_TIMES: &str = "agent.mem_agent_compact_force_times const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info; const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3); const DEFAULT_CDH_API_TIMEOUT: time::Duration = time::Duration::from_secs(50); +const DEFAULT_IMAGE_PULL_TIMEOUT: time::Duration = time::Duration::from_secs(1200); const DEFAULT_CDI_TIMEOUT: time::Duration = time::Duration::from_secs(100); const DEFAULT_CONTAINER_PIPE_SIZE: i32 = 0; const VSOCK_ADDR: &str = "vsock://-1"; @@ -126,6 +128,7 @@ pub struct AgentConfig { pub log_level: slog::Level, pub hotplug_timeout: time::Duration, pub cdh_api_timeout: time::Duration, + pub image_pull_timeout: time::Duration, pub cdi_timeout: time::Duration, pub debug_console_vport: i32, pub log_vport: i32, @@ -158,6 +161,7 @@ pub struct AgentConfigBuilder { pub log_level: Option, pub hotplug_timeout: Option, pub cdh_api_timeout: Option, + pub image_pull_timeout: Option, pub cdi_timeout: Option, pub debug_console_vport: Option, pub log_vport: Option, @@ -251,6 +255,7 @@ impl Default for AgentConfig { log_level: DEFAULT_LOG_LEVEL, hotplug_timeout: DEFAULT_HOTPLUG_TIMEOUT, cdh_api_timeout: DEFAULT_CDH_API_TIMEOUT, + image_pull_timeout: DEFAULT_IMAGE_PULL_TIMEOUT, cdi_timeout: DEFAULT_CDI_TIMEOUT, debug_console_vport: 0, log_vport: 0, @@ -291,6 +296,7 @@ impl FromStr for AgentConfig { ); config_override!(agent_config_builder, agent_config, hotplug_timeout); config_override!(agent_config_builder, agent_config, cdh_api_timeout); + config_override!(agent_config_builder, agent_config, image_pull_timeout); config_override!(agent_config_builder, agent_config, cdi_timeout); config_override!(agent_config_builder, agent_config, debug_console_vport); config_override!(agent_config_builder, agent_config, log_vport); @@ -457,6 +463,15 @@ impl AgentConfig { |cdh_api_timeout: &time::Duration| cdh_api_timeout.as_secs() > 0 ); + // ensure the timeout is a positive value + parse_cmdline_param!( + param, + CDH_IMAGE_PULL_TIMEOUT_OPTION, + config.image_pull_timeout, + get_timeout, + |image_pull_timeout: &time::Duration| image_pull_timeout.as_secs() > 0 + ); + // ensure the timeout is a positive value parse_cmdline_param!( param, @@ -723,7 +738,10 @@ fn get_timeout(param: &str) -> Result { ensure!( matches!( fields[0], - HOTPLUG_TIMOUT_OPTION | CDH_API_TIMOUT_OPTION | CDI_TIMEOUT_OPTION + HOTPLUG_TIMOUT_OPTION + | CDH_API_TIMOUT_OPTION + | CDH_IMAGE_PULL_TIMEOUT_OPTION + | CDI_TIMEOUT_OPTION ), ERR_INVALID_TIMEOUT_KEY ); @@ -1608,6 +1626,7 @@ Caused by: )))] #[case("agent.chd_api_timeout=1", Err(anyhow!(ERR_INVALID_TIMEOUT_KEY)))] #[case("agent.cdh_api_timeout=600", Ok(time::Duration::from_secs(600)))] + #[case("agent.image_pull_timeout=1200", Ok(time::Duration::from_secs(1200)))] #[case("agent.cdi_timeout=320", Ok(time::Duration::from_secs(320)))] fn test_timeout(#[case] param: &str, #[case] expected: Result) { let result = get_timeout(param); From 5bab46022414e1f35bf80f2c90d5afb9d7cc9f8b Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 30 May 2025 17:51:44 +0800 Subject: [PATCH 15/17] chore(deps): update guest-components This patch updates the guest-components to new version with better error logging for CDH. It also allows the config of AA not having a coco_as token config. Also, the new version of CDH requires to build aws-lc-sys thus needs to install cmake for build. See https://github.com/kata-containers/kata-containers/actions/runs/15327923347/job/43127108813?pr=11197#step:6:1609 for details. Besides, the new version of guest-components have some fixes for SNP stack, which requires the updates of trustee side. Signed-off-by: Xynnn007 --- .../static-build/coco-guest-components/Dockerfile | 3 ++- versions.yaml | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/packaging/static-build/coco-guest-components/Dockerfile b/tools/packaging/static-build/coco-guest-components/Dockerfile index a9be1aaec6..79ef04bba2 100644 --- a/tools/packaging/static-build/coco-guest-components/Dockerfile +++ b/tools/packaging/static-build/coco-guest-components/Dockerfile @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: Apache-2.0 -FROM ubuntu:22.04 +FROM ubuntu:24.04 ARG RUST_TOOLCHAIN ENV DEBIAN_FRONTEND=noninteractive @@ -28,6 +28,7 @@ RUN apt-get update && \ libssl-dev \ libtss2-dev \ make \ + cmake \ musl-tools \ openssl \ perl \ diff --git a/versions.yaml b/versions.yaml index b27ad5108a..3666d3d066 100644 --- a/versions.yaml +++ b/versions.yaml @@ -233,18 +233,18 @@ externals: coco-guest-components: description: "Provides attested key unwrapping for image decryption" url: "https://github.com/confidential-containers/guest-components/" - version: "0a06ef241190780840fbb0542e51b198f1f72b0b" + version: "028978dbaef2510ea92bc5038928f1d70c8aaad6" toolchain: "1.80.0" coco-trustee: description: "Provides attestation and secret delivery components" url: "https://github.com/confidential-containers/trustee" - version: "d9eb5e0cb0aca97abe35b58908e061850ff60a51" + version: "a333fa27a7ce538413bad3b537ffbeacf4a349d1" # image / ita_image and image_tag / ita_image_tag must be in sync image: "ghcr.io/confidential-containers/staged-images/kbs" - image_tag: "d9eb5e0cb0aca97abe35b58908e061850ff60a51" + image_tag: "a333fa27a7ce538413bad3b537ffbeacf4a349d1" ita_image: "ghcr.io/confidential-containers/staged-images/kbs-ita-as" - ita_image_tag: "d9eb5e0cb0aca97abe35b58908e061850ff60a51-x86_64" + ita_image_tag: "a333fa27a7ce538413bad3b537ffbeacf4a349d1-x86_64" toolchain: "1.80.0" crio: From 0b3a8c03557b54043fb1c2320b8700fc97ff63c3 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 9 May 2025 17:30:30 +0800 Subject: [PATCH 16/17] initdata: delete coco_as token section in initdata The new version of AA allows the config not having a coco_as token config. If not provided, it will mark as None. Signed-off-by: Xynnn007 --- tests/integration/kubernetes/k8s-initdata.bats | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/integration/kubernetes/k8s-initdata.bats b/tests/integration/kubernetes/k8s-initdata.bats index 5921cbdb94..1dd801dca8 100644 --- a/tests/integration/kubernetes/k8s-initdata.bats +++ b/tests/integration/kubernetes/k8s-initdata.bats @@ -98,10 +98,6 @@ algorithm = "sha256" [data] "aa.toml" = ''' [token_configs] -[token_configs.coco_as] -# TODO: we should fix this on AA side to set this a default value if not set. -url = "${CC_KBS_ADDRESS}" - [token_configs.kbs] url = "${CC_KBS_ADDRESS}" ''' From e0b4cd2dba55cd2f15c5a2f759cdcb1dc12a2c8d Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Wed, 11 Jun 2025 17:44:17 +0800 Subject: [PATCH 17/17] initrd/image: update x86_64 base to ubuntu 24.04 The Multistrap issue has been fixed in noble thus we can use the LTS. Also, this will fix the error reported by CDH ``` /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found ``` Signed-off-by: Xynnn007 --- versions.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versions.yaml b/versions.yaml index 3666d3d066..a2a150703e 100644 --- a/versions.yaml +++ b/versions.yaml @@ -143,7 +143,7 @@ assets: version: "jammy" # 22.04 lTS confidential: name: "ubuntu" - version: "oracular" # 24.10 + version: "noble" # 24.04 LTS mariner: name: "cbl-mariner" version: "3.0" @@ -185,7 +185,7 @@ assets: version: "3.18" confidential: name: "ubuntu" - version: "jammy" # 22.04 LTS + version: "noble" # 24.04 LTS nvidia-gpu: name: "ubuntu" version: "jammy" # 22.04 LTS