diff --git a/Cargo.lock b/Cargo.lock index 6edf7d7..16f7f20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,6 +298,7 @@ dependencies = [ name = "detee-sgx-daemon" version = "0.1.0" dependencies = [ + "anyhow", "chrono", "detee-shared", "env_logger", @@ -314,6 +315,7 @@ dependencies = [ [[package]] name = "detee-shared" version = "0.1.0" +source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared#358c2d84ca092cad5df69ac19cc6acbfb85ee8d7" dependencies = [ "base64", "prost", diff --git a/Cargo.toml b/Cargo.toml index 4c91180..bd206ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,13 @@ prost-types = "0.13.4" tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "fs"] } tonic = "0.12.3" -# detee-shared = { git = "ssh://git@gitea.detee.cloud/noormohammedb/detee-shared" } -detee-shared = { path = "../detee-shared" } +detee-shared = { git = "ssh://git@gitea.detee.cloud/noormohammedb/detee-shared" } +# detee-shared = { path = "../detee-shared" } chrono = "0.4.39" reqwest = "0.12.12" flate2 = "1.0.35" tar = "0.4.43" +anyhow = "1.0.95" [build-dependencies] tonic-build = "0.12.3" diff --git a/build.rs b/build.rs index 86e1797..d976875 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,7 @@ fn main() -> Result<(), Box> { - tonic_build::configure() - .build_server(true) - .compile_protos(&["daemon.proto"], &["proto"]) - .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); + // tonic_build::configure() + // .build_server(true) + // .compile_protos(&["daemon.proto"], &["proto"]) + // .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); Ok(()) } diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..4b9fc33 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,49 @@ +use anyhow::Result; + +use detee_shared::config::Container as ContainerConfig; +use detee_shared::config::Resource as ResourceConfig; + +use crate::package::deploy_enclave; + +#[derive(Debug, Default)] +pub struct DaemonState { + pub containers: Vec, +} + +#[derive(Debug, Default)] +pub struct Container { + pub id: String, + pub name: String, + pub package_path: String, + pub status: String, + pub admin: String, + pub container_resource: ResourceConfig, +} + +impl DaemonState { + pub fn new() -> Self { + Self::default() + } + + pub async fn create_new_container( + &mut self, + ip: String, + req_data: ContainerConfig, + unarchive_dir: String, + ) -> Result<(), Box> { + deploy_enclave(&unarchive_dir).await?; + + let container = Container { + id: "123".to_string(), + name: "".to_string(), + package_path: unarchive_dir, + status: "running".to_string(), + admin: ip, + container_resource: req_data.resource.unwrap(), + }; + + self.containers.push(container); + + Ok(()) + } +} diff --git a/src/grpc.rs b/src/grpc.rs index 9fc6811..31ec549 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -1,23 +1,20 @@ -use chrono::Utc; -use flate2::read::GzDecoder; -use reqwest::Client; -use std::io::BufReader; -use std::path::Path; -use std::process::Command; +use anyhow::Result; +use prost::Message; + use std::sync::Arc; use std::{net::SocketAddr, str::FromStr}; -use tar::Archive; -use tokio::io::AsyncWriteExt; use tokio::sync::RwLock; -use tokio::{fs, fs::File}; use tonic::transport::Server; use detee_shared::pb::daemon::daemon_service_server::{ DaemonService as DaemonServicePB, DaemonServiceServer as DaemonServiceServerPB, }; use detee_shared::pb::daemon::NewContainerRes; -use detee_shared::pb::shared::Container; +use detee_shared::pb::shared::Container as ContainerPB; +use detee_shared::config::Container as ContainerConfig; + +use crate::package::handle_package; use crate::DaemonState; #[derive(Debug, Clone)] @@ -30,7 +27,7 @@ impl DaemonServer { Self { data } } - pub async fn start(&self) -> Result<(), Box> { + pub async fn start(&self) -> Result<()> { let port: String = std::env::var("PORT").unwrap_or_else(|_| "33400".to_string()); let addr = SocketAddr::from_str(format!("0.0.0.0:{port}").as_str())?; @@ -51,19 +48,24 @@ impl DaemonServer { impl DaemonServicePB for DaemonServer { async fn create_container( &self, - request: tonic::Request, + request: tonic::Request, ) -> Result, tonic::Status> { + let req_ip = request.remote_addr().unwrap().to_string(); let req_data = request.into_inner(); - if req_data.package_url.is_none() { - return Err(tonic::Status::data_loss("Package URL not provided")); + if req_data.package_url.is_none() || req_data.resource.is_none() { + return Err(tonic::Status::data_loss("missing some data in request")); } - - let package_url = req_data.package_url.unwrap_or_default(); - let unarchive_dir = handle_package(package_url) + let unarchive_dir = handle_package(req_data.package_url.clone().unwrap_or_default()) .await .map_err(|err| tonic::Status::internal(err.to_string()))?; - deploy_enclave(unarchive_dir) + + let req_container = ContainerConfig::decode(&req_data.encode_to_vec()[..]).unwrap(); + + self.data + .write() + .await + .create_new_container(req_ip, req_container, unarchive_dir) .await .map_err(|err| tonic::Status::internal(err.to_string()))?; @@ -72,64 +74,3 @@ impl DaemonServicePB for DaemonServer { })); } } - -async fn handle_package(package_url: String) -> Result> { - let dir_path = Path::new("./enclave_archives"); - fs::create_dir_all(dir_path).await?; - - let utc_time = Utc::now().format("%Y%m%d%H%M%S"); - - let file_name = format!("{}-enclave_packager.tar.gz", utc_time); - let file_path = dir_path.join(file_name); - if let Err(e) = download_file(&package_url, &file_path).await { - println!("Error downloading file: {:?}", e); - return Err("Error downloading file".into()); - } - - let downloaded_file = std::fs::File::open(file_path)?; - let mut reader = BufReader::new(downloaded_file); - let mut archive = Archive::new(GzDecoder::new(&mut reader)); - - if let Err(er) = archive.entries() { - dbg!(&er); - return Err(format!("Error: file not an archive: {er:?}").into()); - }; - - let unarchive_dir = format!("./enclaves/{}", utc_time); - fs::create_dir_all(Path::new(&unarchive_dir)).await?; - archive.unpack(&unarchive_dir)?; - - Ok(unarchive_dir) -} - -async fn deploy_enclave( - enclave_path: String, - // enclave_name: String, - // publishing_ports: Vec, - // ... -) -> Result<(), Box> { - println!("Deploying enclave: {:?}", enclave_path); - let docker_deploy_str = format!( - "docker run -v {enclave_path}/enclave_packager:/enclave_packager --device /dev/sgx/enclave --device /dev/sgx/provision -p 34500:34500 noormohammedb/occlum-enclave:v1"); - - println!("{}", &docker_deploy_str); - - let child = Command::new("sh") - .arg("-c") - .arg(docker_deploy_str) - .spawn()?; - - dbg!(child); - Ok(()) -} - -async fn download_file(url: &str, file_path: &Path) -> Result<(), Box> { - let client = Client::new(); - let response = client.get(url).send().await?; - let data = response.bytes().await?; - - let mut file = File::create(file_path).await?; - file.write_all(&data).await?; - - Ok(()) -} diff --git a/src/main.rs b/src/main.rs index 339e570..f23b7d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,13 @@ -mod grpc; +pub mod data; +pub mod grpc; +pub mod package; +pub use data::DaemonState; use std::sync::Arc; use grpc::DaemonServer; use tokio::sync::RwLock; -#[derive(Debug, Default)] -pub struct DaemonState { - pub containers: Vec, -} - #[tokio::main] async fn main() -> Result<(), Box> { println!("Detee daemon"); diff --git a/src/package.rs b/src/package.rs new file mode 100644 index 0000000..252956d --- /dev/null +++ b/src/package.rs @@ -0,0 +1,71 @@ +use anyhow::{anyhow, Result}; +use chrono::Utc; +use flate2::read::GzDecoder; +use reqwest::Client; +use std::io::BufReader; +use std::path::Path; +use std::process::Command; +use tar::Archive; +use tokio::io::AsyncWriteExt; +use tokio::{fs, fs::File}; + +pub async fn handle_package(package_url: String) -> Result { + let dir_path = Path::new("./enclave_archives"); + fs::create_dir_all(dir_path).await?; + + let utc_time = Utc::now().format("%Y%m%d%H%M%S"); + + let file_name = format!("{}-enclave_packager.tar.gz", utc_time); + let file_path = dir_path.join(file_name); + if let Err(e) = download_file(&package_url, &file_path).await { + println!("Error downloading file: {:?}", e); + return Err(anyhow!("Error downloading file")); + } + + let downloaded_file = std::fs::File::open(file_path)?; + let mut reader = BufReader::new(downloaded_file); + let mut archive = Archive::new(GzDecoder::new(&mut reader)); + + if let Err(er) = archive.entries() { + dbg!(&er); + return Err(anyhow!("Error: file not an archive: {er:?}")); + }; + + let unarchive_dir = format!("./enclaves/{}", utc_time); + fs::create_dir_all(Path::new(&unarchive_dir)).await?; + archive.unpack(&unarchive_dir)?; + + Ok(unarchive_dir) +} + +pub async fn deploy_enclave( + enclave_path: &str, + // enclave_name: String, + // publishing_ports: Vec, + // ... +) -> Result<(), Box> { + println!("Deploying enclave: {:?}", enclave_path); + let docker_deploy_str = format!( + "docker run -v {enclave_path}/enclave_packager:/enclave_packager --device /dev/sgx/enclave --device /dev/sgx/provision -p 34500:34500 noormohammedb/occlum-enclave:v1"); + + println!("{}", &docker_deploy_str); + + let child = Command::new("sh") + .arg("-c") + .arg(docker_deploy_str) + .spawn()?; + + dbg!(child); + Ok(()) +} + +pub async fn download_file(url: &str, file_path: &Path) -> Result<(), Box> { + let client = Client::new(); + let response = client.get(url).send().await?; + let data = response.bytes().await?; + + let mut file = File::create(file_path).await?; + file.write_all(&data).await?; + + Ok(()) +}