From bf769851f81a399c6e526814479738040c6b4b6f Mon Sep 17 00:00:00 2001 From: Magnus Kulke Date: Thu, 31 Oct 2024 15:16:16 +0100 Subject: [PATCH] agent: perform attestation init w/o process launch This change is motivated by a problem in peerpod's podvms. In this setup the lifecycle of guest components is managed by systemd. The current code skips over init steps like setting the ocicrypt-rs env and initialization of a CDH client in this case. To address this the launch of the processes has been isolated into its own fn. Signed-off-by: Magnus Kulke --- src/agent/src/main.rs | 82 ++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index 8a057bb367..3e2e22d698 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -21,7 +21,7 @@ extern crate slog; use anyhow::{anyhow, Context, Result}; use cfg_if::cfg_if; use clap::{AppSettings, Parser}; -use const_format::concatcp; +use const_format::{concatcp, formatcp}; use nix::fcntl::OFlag; use nix::sys::reboot::{reboot, RebootMode}; use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, VsockAddr}; @@ -29,7 +29,7 @@ use nix::unistd::{self, dup, sync, Pid}; use std::env; use std::ffi::OsStr; use std::fs::{self, File}; -use std::os::unix::fs as unixfs; +use std::os::unix::fs::{self as unixfs, FileTypeExt}; use std::os::unix::io::AsRawFd; use std::path::Path; use std::process::exit; @@ -109,7 +109,18 @@ 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 = "/tmp/ocicrypt_config.json"; +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 +); const DEFAULT_LAUNCH_PROCESS_TIMEOUT: i32 = 6; @@ -408,15 +419,13 @@ async fn start_sandbox( sandbox.lock().await.sender = Some(tx); let gc_procs = config.guest_components_procs; - if gc_procs != GuestComponentsProcs::None { - if !attestation_binaries_available(logger, &gc_procs) { - warn!( - logger, - "attestation binaries requested for launch not available" - ); - } else { - init_attestation_components(logger, config).await?; - } + if !attestation_binaries_available(logger, &gc_procs) { + warn!( + logger, + "attestation binaries requested for launch not available" + ); + } else { + init_attestation_components(logger, config).await?; } // vsock:///dev/vsock, port @@ -447,12 +456,7 @@ fn attestation_binaries_available(logger: &Logger, procs: &GuestComponentsProcs) true } -// Start-up attestation-agent, CDH and api-server-rest if they are packaged in the rootfs -// and the corresponding procs are enabled in the agent configuration. the process will be -// launched in the background and the function will return immediately. -// If the CDH is started, a CDH client will be instantiated and returned. -async fn init_attestation_components(logger: &Logger, config: &AgentConfig) -> Result<()> { - // skip launch of any guest-component +async fn launch_guest_component_procs(logger: &Logger, config: &AgentConfig) -> Result<()> { if config.guest_components_procs == GuestComponentsProcs::None { return Ok(()); } @@ -472,17 +476,6 @@ async fn init_attestation_components(logger: &Logger, config: &AgentConfig) -> R return Ok(()); } - let ocicrypt_config = serde_json::json!({ - "key-providers": { - "attestation-agent":{ - "ttrpc":CDH_SOCKET_URI - } - } - }); - - fs::write(OCICRYPT_CONFIG_PATH, ocicrypt_config.to_string().as_bytes())?; - env::set_var("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH); - debug!( logger, "spawning confidential-data-hub process {}", CDH_PATH @@ -497,9 +490,6 @@ async fn init_attestation_components(logger: &Logger, config: &AgentConfig) -> R ) .map_err(|e| anyhow!("launch_process {} failed: {:?}", CDH_PATH, e))?; - // initialize cdh client - cdh::init_cdh_client(CDH_SOCKET_URI).await?; - // skip launch of api-server-rest if config.guest_components_procs == GuestComponentsProcs::ConfidentialDataHub { return Ok(()); @@ -522,6 +512,34 @@ async fn init_attestation_components(logger: &Logger, config: &AgentConfig) -> R Ok(()) } +// Start-up attestation-agent, CDH and api-server-rest if they are packaged in the rootfs +// and the corresponding procs are enabled in the agent configuration. the process will be +// launched in the background and the function will return immediately. +// If the CDH is started, a CDH client will be instantiated and returned. +async fn init_attestation_components(logger: &Logger, config: &AgentConfig) -> Result<()> { + launch_guest_component_procs(logger, config).await?; + + fs::write(OCICRYPT_CONFIG_PATH, OCICRYPT_CONFIG.as_bytes())?; + env::set_var("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH); + + // If a CDH socket exists, initialize the CDH client + match tokio::fs::metadata(CDH_SOCKET).await { + Ok(md) => { + if md.file_type().is_socket() { + cdh::init_cdh_client(CDH_SOCKET_URI).await?; + } else { + debug!(logger, "File {} is not a socket", CDH_SOCKET); + } + } + Err(err) => warn!( + logger, + "Failed to probe CDH socket file {}: {:?}", CDH_SOCKET, err + ), + } + + Ok(()) +} + fn wait_for_path_to_exist(logger: &Logger, path: &str, timeout_secs: i32) -> Result<()> { let p = Path::new(path); let mut attempts = 0;