diff --git a/dtrfs_api/src/main.rs b/dtrfs_api/src/main.rs index 53deda9..b4f8e18 100644 --- a/dtrfs_api/src/main.rs +++ b/dtrfs_api/src/main.rs @@ -15,8 +15,8 @@ use std::{ io::{BufReader, Read}, }; -const CRT_FILE: &str = "/tmp/certs/guest_api.crt"; -const KEY_FILE: &str = "/tmp/certs/guest_api.key"; +const CRT_FILE: &str = "/tmp/certs/dtrfs_api.crt"; +const KEY_FILE: &str = "/tmp/certs/dtrfs_api.key"; const CMDLINE_FILE: &str = "/proc/cmdline"; lazy_static! { @@ -94,8 +94,8 @@ async fn post_install_form(req: HttpRequest, form: web::Form) -> Ht return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); }; match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile) { - Ok(()) => HttpResponse::Ok().body("Successfully installed OS"), - Err(e) => HttpResponse::BadRequest().body(format!("{e:?}")), + Ok(s) => HttpResponse::Ok().body(s), + Err(e) => HttpResponse::InternalServerError().body(format!("{e:?}")), } } @@ -179,7 +179,15 @@ fn load_rustls_config() -> rustls::ServerConfig { #[actix_web::main] async fn main() -> std::io::Result<()> { - os::try_hot_keyfile().unwrap(); + match os::try_hot_keyfile() { + Ok(_) => { + println!("Hot decryption successful. Booting OS..."); + return Ok(()); + }, + Err(e) => { + println!("Hot decryption failed: {e:?}"); + } + } let config = load_rustls_config(); HttpServer::new(|| { App::new() diff --git a/dtrfs_api/src/os.rs b/dtrfs_api/src/os.rs index 3349d69..7ed90b9 100644 --- a/dtrfs_api/src/os.rs +++ b/dtrfs_api/src/os.rs @@ -11,10 +11,15 @@ use std::{ const SNP_KEYFILE_PATH: &str = "/tmp/detee_snp_keyfile"; const BACKUP_KEYFILE_PATH: &str = "/tmp/detee_backup_keyfile"; -pub fn encrypt_and_install_os(install_url: &str, install_sha: &str, keyfile: &str) -> Result<()> { +pub fn encrypt_and_install_os( + install_url: &str, + install_sha: &str, + keyfile: &str, +) -> Result { let binary_keyfile = BASE64_URL_SAFE.decode(keyfile)?; std::fs::write(BACKUP_KEYFILE_PATH, binary_keyfile)?; - let install_result = Command::new("install_os.sh") + // this path is hardcoded also in the initrd creation script + let install_result = 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) @@ -23,13 +28,20 @@ pub fn encrypt_and_install_os(install_url: &str, install_sha: &str, keyfile: &st if !install_result.status.success() { return Err(anyhow!( - "Could not install OS.\nstdout:{:?}\nstderr:\n{:?}", - install_result.stdout, - install_result.stderr + "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(()) + 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()), + )) } pub fn try_hot_keyfile() -> Result<()> { @@ -46,6 +58,24 @@ pub fn try_backup_keyfile(keyfile: &str) -> Result { Ok("Succesfully mounted /mnt using backup keyfile.".to_string()) } +fn decrypt_and_mount(keyfile_path: &str) -> Result<()> { + let decryption_result = Command::new("cryptsetup") + .arg("open") + .arg("--key-file") + .arg(keyfile_path) + .arg("/dev/vda1") + .arg("root") + .output()?; + if !decryption_result.status.success() { + return Err(anyhow!("Could not decrypt disk.")); + } + let mount_result = Command::new("mount").arg("/dev/mapper/root").arg("/mnt").output()?; + if !mount_result.status.success() { + return Err(anyhow!("Could not mount /dev/mapper/root to /mnt")); + } + Ok(()) +} + pub fn replace_hot_keyfile() -> Result { let _delete_old_keyfile = Command::new("cryptsetup") .arg("luksKillSlot") @@ -72,24 +102,6 @@ pub fn replace_hot_keyfile() -> Result { Ok("Succesfully replaced hot keyfile using SNP KDF.".to_string()) } -fn decrypt_and_mount(keyfile_path: &str) -> Result<()> { - let decryption_result = Command::new("cryptsetup") - .arg("open") - .arg("--key-file") - .arg(keyfile_path) - .arg("/dev/vda1") - .arg("root") - .output()?; - if !decryption_result.status.success() { - return Err(anyhow!("Could not decrypt disk.")); - } - let mount_result = Command::new("mount").arg("/dev/mapper/root").arg("/mnt").output()?; - if !mount_result.status.success() { - return Err(anyhow!("Could not mount /dev/mapper/root to /mnt")); - } - Ok(()) -} - pub fn add_ssh_key(key: &str) -> Result<()> { use std::os::unix::fs::PermissionsExt; if !Path::new("/mnt/etc/os-release").try_exists().is_ok_and(|found| found == true) { diff --git a/scripts/create.sh b/scripts/create.sh index 14db174..5518a8f 100755 --- a/scripts/create.sh +++ b/scripts/create.sh @@ -23,7 +23,7 @@ install_binary $(which mkfs.ext4) install_binary $(which fsarchiver) install_kmod install_busybox -install_guest_api +install_dtrfs_api echo_cyan "Installing scripts..." install_init_script diff --git a/scripts/creator_exports.sh b/scripts/creator_exports.sh index 5d8adcc..7b29b89 100755 --- a/scripts/creator_exports.sh +++ b/scripts/creator_exports.sh @@ -10,9 +10,6 @@ script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # choose a kernel if you don't want to use the active one [[ -n "$KERNEL" ]] || export KERNEL="$(uname -r)" -# this is the DeTEE Guest API that allows you to control the initrd -[[ -n "$GUEST_API_URL" ]] || - export GUEST_API_URL="https://gitea.detee.cloud/ghe0/stuff/releases/download/v0.0.0/guest_api.zst" # this will allow you to grab modules from the machine where the installer is running [[ -n "$GRAB_LOCAL_MODS" ]] || export GRAB_LOCAL_MODS="no" diff --git a/scripts/creator_functions.sh b/scripts/creator_functions.sh index 12f0a12..fdc8881 100644 --- a/scripts/creator_functions.sh +++ b/scripts/creator_functions.sh @@ -32,9 +32,8 @@ install_build_deps() { create_dirs() { rm -rf "$ROOT" 2>/dev/null - mkdir -p "${ROOT}/usr/bin/" mkdir -p "${ROOT}/usr/bin" - mkdir -p "${ROOT}/usr/lib" + mkdir -p "${ROOT}/usr/lib/dtrfs" mkdir -p "${ROOT}/dev" mkdir -p "${ROOT}/etc" mkdir -p "${ROOT}/mnt" @@ -47,9 +46,9 @@ create_dirs() { ln -s usr/bin "${ROOT}/sbin" ln -s usr/lib "${ROOT}/lib" ln -s usr/lib "${ROOT}/lib64" - ln -s lib "${ROOT}/usr/lib64" - ln -s bin "${ROOT}/usr/sbin" - ln -s ../run "${ROOT}/var/run" + ln -s lib "${ROOT}/usr/lib64" + ln -s bin "${ROOT}/usr/sbin" + ln -s ../run "${ROOT}/var/run" } # Installs a library. Expects absolute path. @@ -116,7 +115,8 @@ install_busybox() { install_init_script() { cp ../init.sh "${ROOT}/init" - cp ../init_functions.sh "${ROOT}/" + cp ../init_functions.sh "${ROOT}/usr/lib/dtrfs/" + cp ../install_os.sh "${ROOT}/usr/lib/dtrfs/" } install_module() { @@ -182,13 +182,14 @@ scan_modules() { done <<< "$( echo "$drivers" )" } -install_guest_api() { - echo_cyan "Installing the guest API from https://gitea.detee.cloud/SNP/remote_decryption/" - wget -O guest_api.zst "$GUEST_API_URL" 2> /dev/null - zstd --decompress guest_api.zst - chmod +x guest_api - install_binary "$(pwd)/guest_api" - rm guest_api guest_api.zst +install_dtrfs_api() { + local my_location="$(pwd)" + cd ../../dtrfs_api && cargo build --release || { + echo_yellow "Could not build dtrfs_api. Looking for binary at $(pwd)/dtrfs_api" + } + cd "$my_location" + cp ../../dtrfs_api/target/release/dtrfs_api ./ + install_binary "$(pwd)/dtrfs_api" } create_archive() { @@ -200,5 +201,5 @@ create_archive() { find . | cpio -o -H newc | gzip \ > "${my_location}/detee-$(hostnamectl hostname)-${KERNEL}.cpio.gz" - cd $my_location + cd "$my_location" } diff --git a/scripts/init.sh b/scripts/init.sh index e006b33..31d7c6e 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -1,5 +1,5 @@ #!/bin/bash -source /init_functions.sh +source /usr/lib/dtrfs/init_functions.sh install_url="/tmp/detee_install_url" install_sha="/tmp/detee_install_sha" @@ -14,6 +14,7 @@ setup_network # load this module again cause it fails the first time modprobe sev_guest +create_certs dtrfs_api github_ssh_key diff --git a/scripts/init_functions.sh b/scripts/init_functions.sh index dd736bd..79ab032 100644 --- a/scripts/init_functions.sh +++ b/scripts/init_functions.sh @@ -25,25 +25,17 @@ create_mounts() { ln -sfT /proc/self/fd/2 /dev/stderr } -try_hot_decrypt() { - [[ -f "$snp_key_file" ]] && { - cryptsetup open --key-file $snp_key_file /dev/vda1 root || return 1 - mount /dev/mapper/root /mnt || return 1 - return 0 - } - return 1 -} - create_certs() { cert_dir="/tmp/certs" - key="$cert_dir/guest_api.key" - cert="$cert_dir/guest_api.crt" - subject="/C=W3/O=DeTEE/OU=COCO/CN=guest-api" + key="$cert_dir/dtrfs_api.key" + cert="$cert_dir/dtrfs_api.crt" + subject="/C=W3/O=DeTEE/OU=COCO/CN=dtrfs-api" mkdir -p "$cert_dir" openssl genpkey -algorithm RSA -out "$key" \ -pkeyopt rsa_keygen_bits:4096 2>/dev/null openssl req -x509 -new \ -key "$key" -out "$cert" \ + -addext "subjectAltName=DNS:dtrfs-api" \ -days 365 -subj "$subject" 2>/dev/null } diff --git a/dtrfs_api/install_os.sh b/scripts/install_os.sh similarity index 77% rename from dtrfs_api/install_os.sh rename to scripts/install_os.sh index 42160b2..38d6701 100755 --- a/dtrfs_api/install_os.sh +++ b/scripts/install_os.sh @@ -2,12 +2,12 @@ # This script is called by dtrfs_api to install an OS. -[[ -z "$INSTALL_URL" ]] || { +[[ -z "$INSTALL_URL" ]] && { echo "Did not find INSTALL_URL env variable". exit 1 } -[[ -z "$INSTALL_URL" ]] || { +[[ -z "$INSTALL_URL" ]] && { echo "Did not find INSTALL_SHA env variable". exit 2 } @@ -33,23 +33,23 @@ echo === Creating partition /dev/vda1 echo w ) | fdisk /dev/vda echo "=== Formatting /dev/vda1 using cryptsetup luksFormat and opening as root" -cryptsetup luksFormat --batch-mode -d $root_keyfile /dev/vda1 +cryptsetup luksFormat --batch-mode -d $ROOT_KEYFILE /dev/vda1 || exit 5 [[ -f "$SNP_KEY_FILE" ]] && { echo "Adding LUKS slot via SNP KDF key found at $SNP_KEY_FILE" - cryptsetup luksAddKey \ - --key-file $ROOT_KEYFILE \ + cryptsetup luksAddKey \ + --key-file $ROOT_KEYFILE \ --new-keyfile $SNP_KEY_FILE /dev/vda1 } -cryptsetup open -d $ROOT_KEYFILE /dev/vda1 root +cryptsetup open -d $ROOT_KEYFILE /dev/vda1 root || exit 6 echo "=== Formatting /dev/mapper/root as ext4 and mounting at /mnt" -mkfs.ext4 /dev/mapper/root -mount /dev/mapper/root /mnt +mkfs.ext4 /dev/mapper/root || exit 7 +mount /dev/mapper/root /mnt || exit 8 echo "=== Downloading OS template from $INSTALL_URL and verifying hash" wget -O /mnt/template.fsa "$INSTALL_URL" || { echo "Failed to download $INSTALL_URL" - exit 5 + exit 9 } -sha256sum /mnt/template.fsa | grep $(cat ${INSTALL_SHA}) || exit 1 +sha256sum /mnt/template.fsa | grep "${INSTALL_SHA}" || exit 1 echo "=== Installing OS template" fsarchiver restdir /mnt/template.fsa / rm /mnt/template.fsa diff --git a/scripts/remote_create.sh b/scripts/remote_create.sh index d5d7ab2..37dae76 100755 --- a/scripts/remote_create.sh +++ b/scripts/remote_create.sh @@ -30,8 +30,16 @@ fi set -e -mkdir -p tmp -tar cf tmp/dtrfs.tar *.sh +# TODO: test if this works +mkdir -p tmp build +my_location="$(pwd)" +cd ../dtrfs_api && cargo build --release || { + echo Could not build dtrfs_api + exit 1 +} +cd "$my_location" +cp ../dtrfs_api/target/release/dtrfs_api ./build/ +tar cf tmp/dtrfs.tar *.sh build/dtrfs_api arch_guest_mods $ssh $server rm -rf ${dir} $ssh $server mkdir -p ${dir} $scp tmp/dtrfs.tar ${scp_server}:${dir}