From 65fe44026680ed94fca89e9916d4ab86ef9260c4 Mon Sep 17 00:00:00 2001 From: piotrpalcz Date: Tue, 19 Dec 2023 14:07:08 +0000 Subject: [PATCH] Use randomly generated key in image-rs to secure image layers in sefs Signed-off-by: piotrpalcz --- image-rs/.vscode/settings.json | 9 ++ image-rs/Cargo.toml | 1 - image-rs/src/snapshots/occlum/unionfs.rs | 114 ++++++++++++----------- 3 files changed, 68 insertions(+), 56 deletions(-) create mode 100644 image-rs/.vscode/settings.json diff --git a/image-rs/.vscode/settings.json b/image-rs/.vscode/settings.json new file mode 100644 index 000000000..12faa86a7 --- /dev/null +++ b/image-rs/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "rust-analyzer.linkedProjects": [ + "./Cargo.toml", + "./Cargo.toml", + "./Cargo.toml", + "./Cargo.toml", + "./Cargo.toml" + ] +} \ No newline at end of file diff --git a/image-rs/Cargo.toml b/image-rs/Cargo.toml index b40ff36f2..d599bad79 100644 --- a/image-rs/Cargo.toml +++ b/image-rs/Cargo.toml @@ -32,7 +32,6 @@ oci-spec = "0.6.2" ocicrypt-rs = { path = "../ocicrypt-rs", default-features = false, features = ["async-io"], optional = true } prost = { workspace = true, optional = true } protobuf = { workspace = true, optional = true } -rand = "0.8.5" reqwest = { workspace = true, features = ["json"], optional = true } sequoia-openpgp = { version = "1.7.0", default-features = false, features = ["compression", "crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"], optional = true } serde = { workspace = true, features = ["serde_derive", "rc"] } diff --git a/image-rs/src/snapshots/occlum/unionfs.rs b/image-rs/src/snapshots/occlum/unionfs.rs index 8c7bb4819..c9e00cc93 100644 --- a/image-rs/src/snapshots/occlum/unionfs.rs +++ b/image-rs/src/snapshots/occlum/unionfs.rs @@ -5,18 +5,16 @@ // This unionfs file is used for occlum only use std::fs; -use std::fs::{File, OpenOptions}; -use std::io::{Error, ErrorKind, self, Write}; +use std::fs::File; +use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::atomic::AtomicUsize; -use std::ffi::CString; use anyhow::{anyhow, Context, Result}; use dircpy::CopyBuilder; use fs_extra; use fs_extra::dir; use nix::mount::MsFlags; -use rand::Rng; use ocicrypt_rs::blockcipher::rand::rand_bytes; @@ -53,28 +51,31 @@ fn create_dir(create_path: &Path) -> Result<()> { Ok(()) } -fn create_key_file(path: &PathBuf, key: &str) -> Result<()> { - let mut file = File::create(path) - .with_context(|| format!("Failed to create file: {:?}", path))?; - - file.write_all(key.as_bytes()) - .with_context(|| format!("Failed to write to file: {:?}", path))?; - - Ok(()) - -} // returns randomly generted random 128 bit key fn generate_random_key() -> String { - let mut key: [u8; 16] = [0u8; 16]; rand_bytes(&mut key).expect("Random fill failed"); - let formatted_key = key.iter().map(|byte| format!("{:02x}", byte)).collect::>().join("-"); + let formatted_key = key + .iter() + .map(|byte| format!("{:02x}", byte)) + .collect::>() + .join("-"); formatted_key } +fn create_key_file(path: &PathBuf, key: &str) -> Result<()> { + let mut file = + File::create(path).with_context(|| format!("Failed to create file: {:?}", path))?; + + file.write_all(key.as_bytes()) + .with_context(|| format!("Failed to write to file: {:?}", path))?; + + Ok(()) +} + fn create_environment(mount_path: &Path) -> Result<()> { let mut from_paths = Vec::new(); let mut copy_options = dir::CopyOptions::new(); @@ -97,7 +98,6 @@ fn create_environment(mount_path: &Path) -> Result<()> { if fs::symlink_metadata(ld_lib.as_path()).is_ok() { fs::remove_file(ld_lib)?; } - fs_extra::copy_items(&from_paths, &path_lib64, ©_options)?; from_paths.clear(); @@ -138,10 +138,9 @@ fn create_environment(mount_path: &Path) -> Result<()> { impl Snapshotter for Unionfs { fn mount(&mut self, layer_path: &[&str], mount_path: &Path) -> Result { - // From the description of https://github.com/occlum/occlum/blob/master/docs/runtime_mount.md#1-mount-trusted-unionfs-consisting-of-sefss , - // the source type of runtime mount is "unionfs". let fs_type = String::from("sefs"); let source = Path::new(&fs_type); + let flags = MsFlags::empty(); if !mount_path.exists() { fs::create_dir_all(mount_path)?; @@ -154,17 +153,53 @@ impl Snapshotter for Unionfs { .file_name() .ok_or(anyhow!("Unknown error: file name parse fail"))?; - // For mounting trusted UnionFS at runtime of occlum, - // you can refer to https://github.com/occlum/occlum/blob/master/docs/runtime_mount.md#1-mount-trusted-unionfs-consisting-of-sefss. let random_key = generate_random_key(); + let new_key_path = Path::new("/new_key"); + fs::create_dir_all(new_key_path)?; + create_key_file(&PathBuf::from(&new_key_path.join("key.txt")), &random_key).map_err( + |e| { + anyhow!( + "failed to write key file {:?} with error: {}", + "/key.txt", + e + ) + }, + )?; + + let key_mount_options = format!( + "dir={}", + Path::new("/images") + .join(cid) + .join("keys/sefs/lower") + .display() + ); + + let keys_mount_path = Path::new("/keys"); + nix::mount::mount( + Some(source), + keys_mount_path, + Some(fs_type.as_str()), + flags, + Some(key_mount_options.as_str()), + ) + .map_err(|e| { + anyhow!( + "failed to mount {:?} to {:?}, with error: {}", + source, + keys_mount_path, + e + ) + })?; + + fs::copy("/new_key/key.txt", "/keys/key.txt")?; + nix::mount::umount(keys_mount_path)?; + let options = format!( "dir={},key={}", Path::new("/images").join(cid).join("sefs/lower").display(), random_key ); - let flags = MsFlags::empty(); - nix::mount::mount( Some(source), mount_path, @@ -193,41 +228,10 @@ impl Snapshotter for Unionfs { .ok_or(anyhow!("Pop() failed from Vec"))?; CopyBuilder::new(layer, mount_path).overwrite(true).run()?; } - - let sealing_keys_dir = Path::new("/keys").join(cid).join("keys"); - fs::create_dir_all(sealing_keys_dir.clone())?; - let key_file_create_path = sealing_keys_dir.join("key.txt"); - - create_key_file(&PathBuf::from(&key_file_create_path), &random_key) - .map_err(|e| { - anyhow!( - "failed to write key file {:?} with error: {}", - key_file_create_path, - e - ) - })?; - - let hostfs_fstype = String::from("hostfs"); - let keys_mount_path = Path::new("/keys"); - - let mountpoint_c = CString::new(keys_mount_path.to_str().unwrap()).unwrap(); - nix::mount::mount( - Some(hostfs_fstype.as_str()), - mountpoint_c.as_c_str(), - Some(hostfs_fstype.as_str()), - flags, - Some("dir=/keys"), - ).map_err(|e| { - anyhow!( - "failed to mount {:?} to {:?}, with error: {}", - hostfs_fstype.as_str(), - keys_mount_path, - e - ) - })?; // create environment for Occlum create_environment(mount_path)?; + nix::mount::umount(mount_path)?; Ok(MountPoint {