improved /install
This commit is contained in:
		
							parent
							
								
									7864c53236
								
							
						
					
					
						commit
						b1049c4dcc
					
				
							
								
								
									
										38
									
								
								dtrfs_api/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										38
									
								
								dtrfs_api/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
| version = 4 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "actix-codec" | ||||
| @ -678,6 +678,9 @@ dependencies = [ | ||||
|  "serde", | ||||
|  "sev", | ||||
|  "sha3", | ||||
|  "tokio", | ||||
|  "tokio-stream", | ||||
|  "tokio-util", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -2104,9 +2107,9 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio" | ||||
| version = "1.41.1" | ||||
| version = "1.42.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" | ||||
| checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" | ||||
| dependencies = [ | ||||
|  "backtrace", | ||||
|  "bytes", | ||||
| @ -2116,9 +2119,21 @@ dependencies = [ | ||||
|  "pin-project-lite", | ||||
|  "signal-hook-registry", | ||||
|  "socket2", | ||||
|  "tokio-macros", | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-macros" | ||||
| version = "2.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-rustls" | ||||
| version = "0.26.0" | ||||
| @ -2131,10 +2146,21 @@ dependencies = [ | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-util" | ||||
| version = "0.7.12" | ||||
| name = "tokio-stream" | ||||
| version = "0.1.17" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" | ||||
| checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "pin-project-lite", | ||||
|  "tokio", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-util" | ||||
| version = "0.7.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "futures-core", | ||||
|  | ||||
| @ -11,6 +11,9 @@ regex = "1.11.1" | ||||
| sev = { version = "4.0", default-features = false, features = ['crypto_nossl','snp'] } | ||||
| ed25519-dalek = { version = "2.1.1", features = ["pem", "pkcs8"] } | ||||
| lazy_static = "1.5.0" | ||||
| tokio = { version = "1.42.0", features = ["full"] } | ||||
| tokio-util = "0.7.13" | ||||
| tokio-stream = { version = "0.1.17", features = ["io-util"] } | ||||
| actix-web = { version = "4.9.0", features = ["rustls-0_23"] } | ||||
| sha3 = "0.10.8" | ||||
| rustls = "0.23.18" | ||||
|  | ||||
| @ -93,8 +93,8 @@ async fn post_install_form(req: HttpRequest, form: web::Form<InstallForm>) -> Ht | ||||
|     if let Err(e) = verify(&req) { | ||||
|         return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); | ||||
|     }; | ||||
|     match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile) { | ||||
|         Ok(s) => HttpResponse::Ok().body(s), | ||||
|     match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile).await { | ||||
|         Ok(s) => s, | ||||
|         Err(e) => HttpResponse::InternalServerError().body(format!("{e:?}")), | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,47 +1,67 @@ | ||||
| use crate::snp::get_derived_key; | ||||
| use actix_web::{web::Bytes, HttpResponse}; | ||||
| use anyhow::{anyhow, Result}; | ||||
| use base64::prelude::{Engine, BASE64_URL_SAFE}; | ||||
| use std::process::Command; | ||||
| use std::{ | ||||
|     fs::File, | ||||
|     io::{BufRead, BufReader, Write}, | ||||
|     path::Path, | ||||
|     process::Command, | ||||
|     process::Stdio, | ||||
| }; | ||||
| 
 | ||||
| const SNP_KEYFILE_PATH: &str = "/tmp/detee_snp_keyfile"; | ||||
| const BACKUP_KEYFILE_PATH: &str = "/tmp/detee_backup_keyfile"; | ||||
| 
 | ||||
| pub fn encrypt_and_install_os( | ||||
| pub async fn encrypt_and_install_os( | ||||
|     install_url: &str, | ||||
|     install_sha: &str, | ||||
|     keyfile: &str, | ||||
| ) -> Result<String> { | ||||
|     let binary_keyfile = BASE64_URL_SAFE.decode(keyfile)?; | ||||
|     std::fs::write(BACKUP_KEYFILE_PATH, binary_keyfile)?; | ||||
|     // this path is hardcoded also in the initrd creation script
 | ||||
|     let install_result = Command::new("/usr/lib/dtrfs/install_os.sh") | ||||
| ) -> Result<HttpResponse, actix_web::Error> { | ||||
|     use tokio::process::Command; | ||||
|     use tokio::io::{BufReader, AsyncBufReadExt}; | ||||
|     use tokio_stream::{StreamExt, wrappers::LinesStream}; | ||||
| 
 | ||||
|     let binary_keyfile = base64::engine::general_purpose::URL_SAFE.decode(keyfile) | ||||
|         .map_err(|e| actix_web::error::ErrorBadRequest(e.to_string()))?; | ||||
| 
 | ||||
|     // Write the decoded keyfile to the backup path asynchronously
 | ||||
|     tokio::fs::write(BACKUP_KEYFILE_PATH, &binary_keyfile) | ||||
|         .await | ||||
|         .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?; | ||||
| 
 | ||||
|     // Spawn the installation script as a child process
 | ||||
|     let mut child = Command::new("/usr/lib/dtrfs/install_os.sh") | ||||
|         .env("INSTALL_URL", install_url) | ||||
|         .env("INSTALL_SHA", install_sha) | ||||
|         .env("SNP_KEY_FILE", SNP_KEYFILE_PATH) | ||||
|         .env("ROOT_KEYFILE", BACKUP_KEYFILE_PATH) | ||||
|         .output()?; | ||||
|         .stdout(Stdio::piped()) | ||||
|         .stderr(Stdio::piped()) | ||||
|         .spawn() | ||||
|         .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?; | ||||
| 
 | ||||
|     if !install_result.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "OS installation script failed.\nScript stdout:\n{}\nScript stderr:\n{}", | ||||
|             String::from_utf8(install_result.stdout) | ||||
|                 .unwrap_or("Could not grab stdout from installation script.".to_string()), | ||||
|             String::from_utf8(install_result.stderr) | ||||
|                 .unwrap_or("Could not grab stderr from installation script.".to_string()), | ||||
|         )); | ||||
|     } | ||||
|     Ok(format!( | ||||
|         "Successfully installed OS. Script stdout:\n{}\nScript stderr:\n{}", | ||||
|         String::from_utf8(install_result.stdout) | ||||
|             .unwrap_or("Could not grab stdout from installation script.".to_string()), | ||||
|         String::from_utf8(install_result.stderr) | ||||
|             .unwrap_or("Could not grab stderr from installation script.".to_string()), | ||||
|     )) | ||||
|     // Take stdout and stderr from the child process
 | ||||
|     let stdout = child.stdout.take().ok_or_else(|| { | ||||
|         actix_web::error::ErrorInternalServerError("Failed to capture stdout".to_string()) | ||||
|     })?; | ||||
|     let stderr = child.stderr.take().ok_or_else(|| { | ||||
|         actix_web::error::ErrorInternalServerError("Failed to capture stderr".to_string()) | ||||
|     })?; | ||||
| 
 | ||||
|     // Merge stdout and stderr into a single stream
 | ||||
|     let stdout_lines = LinesStream::new(BufReader::new(stdout).lines()); | ||||
|     let stderr_lines = LinesStream::new(BufReader::new(stderr).lines()); | ||||
|     let merged_stream = stdout_lines.merge(stderr_lines).map(|line_result| { | ||||
|         line_result | ||||
|             .map(|line| Bytes::from(line + "\n")) | ||||
|             .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string())) | ||||
|     }); | ||||
| 
 | ||||
|     // Return the merged stream as the HTTP response
 | ||||
|     Ok(HttpResponse::Ok() | ||||
|         .content_type("text/plain; charset=utf-8") | ||||
|         .streaming(merged_stream)) | ||||
| } | ||||
| 
 | ||||
| pub fn try_hot_keyfile() -> Result<()> { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user