From f476d671edd1161223d9a7e2cfd19cfd1b5f73f8 Mon Sep 17 00:00:00 2001 From: Biao Lu Date: Wed, 23 Aug 2023 14:26:48 +0800 Subject: [PATCH] agent: Launch the confidential data hub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's introduce a new method to start the confidential data hub and the attestation agent. The former depends on the later, and it needs to be started before the RPC server. Starting the attestation components is based on whether the confidential containers guest components binaries are found in the rootfs. Fixes: #7544 Signed-off-by: Biao Lu Signed-off-by: Fabiano FidĂȘncio Signed-off-by: Linda Yu Co-authored-by: stevenhorsman Co-authored-by: Jakob Naucke Co-authored-by: Wang, Arron Co-authored-by: zhouliang121 Co-authored-by: Alex Carter Co-authored-by: Suraj Deshmukh Co-authored-by: Xynnn007 --- src/agent/Cargo.lock | 27 ++++++++++++++ src/agent/Cargo.toml | 11 +++--- src/agent/src/main.rs | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 4c65509bd3..9e194700f5 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -817,6 +817,26 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -2081,6 +2101,7 @@ dependencies = [ "cfg-if 1.0.0", "cgroups-rs", "clap", + "const_format", "futures", "http", "image-rs", @@ -5210,6 +5231,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "universal-hash" version = "0.5.1" diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml index 31092c0aa4..ff7dd65f7f 100644 --- a/src/agent/Cargo.toml +++ b/src/agent/Cargo.toml @@ -26,6 +26,7 @@ url = "2.5.0" kata-sys-util = { path = "../libs/kata-sys-util" } kata-types = { path = "../libs/kata-types" } safe-path = { path = "../libs/safe-path" } +const_format = "0.2.30" # Async helpers async-trait = "0.1.42" @@ -36,7 +37,7 @@ futures = "0.3.30" tokio = { version = "1.28.1", features = ["full"] } tokio-vsock = "0.3.1" -netlink-sys = { version = "0.7.0", features = ["tokio_socket",]} +netlink-sys = { version = "0.7.0", features = ["tokio_socket"] } rtnetlink = "0.8.0" netlink-packet-utils = "0.4.1" ipnetwork = "0.17.0" @@ -62,7 +63,7 @@ cgroups = { package = "cgroups-rs", version = "0.3.3" } tracing = "0.1.26" tracing-subscriber = "0.2.18" tracing-opentelemetry = "0.13.0" -opentelemetry = { version = "0.14.0", features = ["rt-tokio-current-thread"]} +opentelemetry = { version = "0.14.0", features = ["rt-tokio-current-thread"] } vsock-exporter = { path = "vsock-exporter" } # Configuration @@ -87,16 +88,14 @@ rstest = "0.18.0" async-std = { version = "1.12.0", features = ["attributes"] } [workspace] -members = [ - "rustjail", -] +members = ["rustjail"] [profile.release] lto = true [features] # The default-pull feature would support all pull types, including sharing images by virtio-fs and pulling images in the guest -default-pull = [ "guest-pull" ] +default-pull = ["guest-pull"] seccomp = ["rustjail/seccomp"] standard-oci-runtime = ["rustjail/standard-oci-runtime"] agent-policy = ["http", "openssl", "reqwest"] diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index e79ec6fb35..e6fba188b3 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -22,6 +22,7 @@ extern crate slog; use anyhow::{anyhow, Context, Result}; use cfg_if::cfg_if; use clap::{AppSettings, Parser}; +use const_format::concatcp; use nix::fcntl::OFlag; use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, VsockAddr}; use nix::unistd::{self, dup, Pid}; @@ -32,6 +33,7 @@ use std::os::unix::fs as unixfs; use std::os::unix::io::AsRawFd; use std::path::Path; use std::process::exit; +use std::process::Command; use std::sync::Arc; use tracing::{instrument, span}; @@ -91,6 +93,20 @@ cfg_if! { const NAME: &str = "kata-agent"; +const UNIX_SOCKET_PREFIX: &str = "unix://"; + +const AA_PATH: &str = "/usr/local/bin/attestation-agent"; +const AA_ATTESTATION_SOCKET: &str = + "/run/confidential-containers/attestation-agent/attestation-agent.sock"; +const AA_ATTESTATION_URI: &str = concatcp!(UNIX_SOCKET_PREFIX, AA_ATTESTATION_SOCKET); + +const CDH_PATH: &str = "/usr/local/bin/confidential-data-hub"; +const CDH_SOCKET: &str = "/run/confidential-containers/cdh.sock"; + +const API_SERVER_PATH: &str = "/usr/local/bin/api-server-rest"; + +const DEFAULT_LAUNCH_PROCESS_TIMEOUT: i32 = 6; + lazy_static! { static ref AGENT_CONFIG: AgentConfig = // Note: We can't do AgentOpts.parse() here to send through the processed arguments to AgentConfig @@ -384,6 +400,10 @@ async fn start_sandbox( let (tx, rx) = tokio::sync::oneshot::channel(); sandbox.lock().await.sender = Some(tx); + if Path::new(CDH_PATH).exists() && Path::new(AA_PATH).exists() { + init_attestation_components(logger)?; + } + // vsock:///dev/vsock, port let mut server = rpc::start(sandbox.clone(), config.server_addr.as_str(), init_mode).await?; server.start().await?; @@ -394,6 +414,73 @@ async fn start_sandbox( Ok(()) } +// Start-up attestation-agent, CDH and api-server-rest if they are packaged in the rootfs +fn init_attestation_components(logger: &Logger) -> Result<()> { + // The Attestation Agent will run for the duration of the guest. + launch_process( + logger, + AA_PATH, + &vec!["--attestation_sock", AA_ATTESTATION_URI], + AA_ATTESTATION_SOCKET, + DEFAULT_LAUNCH_PROCESS_TIMEOUT, + ) + .map_err(|e| anyhow!("launch_process {} failed: {:?}", AA_PATH, e))?; + + if let Err(e) = launch_process( + logger, + CDH_PATH, + &vec![], + CDH_SOCKET, + DEFAULT_LAUNCH_PROCESS_TIMEOUT, + ) { + error!(logger, "launch_process {} failed: {:?}", CDH_PATH, e); + } + + Ok(()) +} + +fn wait_for_path_to_exist(logger: &Logger, path: &str, timeout_secs: i32) -> Result<()> { + let p = Path::new(path); + let mut attempts = 0; + loop { + std::thread::sleep(std::time::Duration::from_secs(1)); + if p.exists() { + return Ok(()); + } + if attempts >= timeout_secs { + break; + } + attempts += 1; + info!( + logger, + "waiting for {} to exist (attempts={})", path, attempts + ); + } + + Err(anyhow!("wait for {} to exist timeout.", path)) +} + +fn launch_process( + logger: &Logger, + path: &str, + args: &Vec<&str>, + unix_socket_path: &str, + timeout_secs: i32, +) -> Result<()> { + if !Path::new(path).exists() { + return Err(anyhow!("path {} does not exist.", path)); + } + if !unix_socket_path.is_empty() && Path::new(unix_socket_path).exists() { + fs::remove_file(unix_socket_path)?; + } + Command::new(path).args(args).spawn()?; + if !unix_socket_path.is_empty() && timeout_secs > 0 { + wait_for_path_to_exist(logger, unix_socket_path, timeout_secs)?; + } + + Ok(()) +} + // init_agent_as_init will do the initializations such as setting up the rootfs // when this agent has been run as the init process. fn init_agent_as_init(logger: &Logger, unified_cgroup_hierarchy: bool) -> Result<()> {