From 3236850c48b953d061d23793231ad222e025b39a Mon Sep 17 00:00:00 2001 From: oluceps Date: Tue, 19 Nov 2024 04:35:33 +0800 Subject: [PATCH] + refine codes --- module/templateType.nix | 6 -- src/cmd/deploy.rs | 115 ++++++++++++++++----------------------- src/helper/secret_buf.rs | 44 +++++++++++++-- src/helper/stored.rs | 10 ++-- 4 files changed, 89 insertions(+), 86 deletions(-) diff --git a/module/templateType.nix b/module/templateType.nix index 87f1d14..efb27fb 100644 --- a/module/templateType.nix +++ b/module/templateType.nix @@ -17,12 +17,6 @@ in { templateType = types.submodule (submod: { options = { - type = mkOption { - type = types.str; - default = "template"; - readOnly = true; - description = "Identifier of option type"; - }; content = mkOption { type = types.str; default = ""; diff --git a/src/cmd/deploy.rs b/src/cmd/deploy.rs index dff0319..b5b70ab 100644 --- a/src/cmd/deploy.rs +++ b/src/cmd/deploy.rs @@ -1,7 +1,7 @@ use std::{ collections::HashMap, - fs::{self, OpenOptions, Permissions, ReadDir}, - io::{self, ErrorKind, Write}, + fs::{self, Permissions, ReadDir}, + io::{self, ErrorKind}, os::unix::fs::PermissionsExt, path::PathBuf, rc::Rc, @@ -9,7 +9,6 @@ use std::{ use crate::{ helper::{ - self, secret_buf::{Plain, SecBuf}, stored::{InStore, SecMap, SecPath}, }, @@ -37,44 +36,23 @@ impl HostKey { const KEY_TYPE: &str = "ed25519"; -fn deploy_to_fs( - ctx: SecBuf, - item: impl crate::profile::DeployFactor, - dst: PathBuf, -) -> Result<()> { - let mut the_file = { - let mode = crate::parser::parse_octal_str(item.mode()) - .map_err(|e| eyre!("parse octal permission err: {}", e))?; - let permissions = Permissions::from_mode(mode); - - let file = OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(dst)?; - - file.set_permissions(permissions)?; - - helper::set_owner_group::set_owner_and_group(&file, item.owner(), item.group())?; - - file +macro_rules! impl_get_settings { + ([ $($field:ident),+ $(,)? ]) => { + impl Profile { + $( + fn $field(&self) -> &str { + self.settings.$field.as_str() + } + )+ + } }; - the_file.write_all(ctx.buf_ref())?; - Ok(()) } +impl_get_settings!([decrypted_mount_point, decrypted_dir, decrypted_dir_for_user]); + impl Profile { - pub fn get_decrypted_mount_point_path(&self) -> String { - self.settings.decrypted_mount_point.to_string() - } - pub fn get_decrypt_dir_path(&self) -> String { - self.settings.decrypted_dir.to_string() - } - pub fn get_decrypt_dir_path_for_user(&self) -> String { - self.settings.decrypted_dir_for_user.to_string() - } pub fn read_decrypted_mount_point(&self) -> std::io::Result { - fs::read_dir(self.get_decrypted_mount_point_path()) + fs::read_dir(self.decrypted_mount_point()) } pub fn get_host_key_identity(&self) -> Result { @@ -108,12 +86,12 @@ impl Profile { error!("{}", err); return Err(eyre!(err)); } - let path = self.get_decrypted_mount_point_path(); - info!("creating mount point {}", path.clone()); - fs::create_dir_all(path.clone()).wrap_err_with(|| { + let path = self.decrypted_mount_point(); + info!("creating mount point {}", path); + fs::create_dir_all(path).wrap_err_with(|| { format!( "creating decrypted mountpoint: {:?}", - self.get_decrypted_mount_point_path() + self.decrypted_mount_point() ) })?; Mount::builder() @@ -121,7 +99,7 @@ impl Profile { .flags(MountFlags::NOSUID) .data("relatime") .data("mode=751") - .mount(String::default(), self.get_decrypted_mount_point_path()) + .mount(String::default(), self.decrypted_mount_point()) .map(|_| ()) // not needed. .wrap_err(eyre!("mount tmpfs error")) } @@ -166,27 +144,26 @@ impl Profile { let if_early = |i: &String| -> bool { self.before_userborn.contains(i) == early }; - let secrets_to_deploy = self.secrets.iter().filter(|i| if_early(i.0)); + let secrets = self.secrets.values().filter(|i| if_early(&i.id)); - let templates_map_iter = self.templates.iter().filter(|i| if_early(i.0)); + let templates = self.templates.iter().filter(|i| if_early(i.0)); - let plain_map: SecMap> = - SecMap::>::from_iter(secrets_to_deploy.into_iter().map(|(_, v)| v)) - .renced_stored( - self.settings.cache_in_store.clone().into(), - self.settings.host_pubkey.as_str(), - ) - .bake_ctx()? - .inner() - .into_iter() - .map(|(s, c)| (s, c.decrypt(host_prv_key).expect("err").inner())) - .collect(); + let plain_map: SecMap> = SecMap::>::from_iter(secrets) + .renced_stored( + self.settings.cache_in_store.clone().into(), + self.settings.host_pubkey.as_str(), + ) + .bake()? + .inner() + .iter() + .map(|(s, c)| (*s, c.decrypt(host_prv_key).expect("err").inner())) + .collect(); - let generation_count = self.init_decrypted_mount_point()?; + let generation = self.init_decrypted_mount_point()?; let target_extract_dir_with_gen = { - let mut p = PathBuf::from(self.get_decrypted_mount_point_path()); - p.push(generation_count.to_string()); + let mut p = PathBuf::from(self.decrypted_mount_point()); + p.push(generation.to_string()); debug!("target extract dir with generation number: {:?}", p); @@ -229,13 +206,13 @@ impl Profile { .inner_ref() .iter() .map(|(n, c)| { - let ctx = SecBuf::::new(c.clone()); + let plain = SecBuf::::new(c.clone()); let item = n as &dyn DeployFactor; let dst: PathBuf = generate_dst!(item, self.settings, target_extract_dir_with_gen); info!("secret {} -> {}", item.name(), dst.display(),); - deploy_to_fs(ctx, *n, dst) + plain.deploy_to_fs(*n, dst) }) .for_each(|res| { if let Err(e) = res { @@ -246,8 +223,8 @@ impl Profile { if !self.templates.is_empty() { info!("start templates deployment"); - // new map with {{ hash }} String as key, ctx as value - let hashstr_ctx_map: HashMap<&str, &Vec> = plain_map + // new map with {{ hash }} String as key, content as value + let hashstr_content_map: HashMap<&str, &Vec> = plain_map .inner_ref() .iter() .map(|(k, v)| { @@ -261,14 +238,14 @@ impl Profile { }) .collect(); - templates_map_iter + templates .map(|(_, t)| { let mut template = t.content.clone(); let hashstrs_of_it = t.parse_hash_str_list().expect("parse template"); let trim_the_insertial = t.trim; - hashstr_ctx_map + hashstr_content_map .iter() .filter(|(k, _)| { let mut v = Vec::new(); @@ -297,29 +274,29 @@ impl Profile { let dst = generate_dst!(item, self.settings, target_extract_dir_with_gen); info!("template {} -> {}", item.name(), dst.display(),); - deploy_to_fs(SecBuf::::new(template.into_bytes()), t, dst) + SecBuf::::new(template.into_bytes()).deploy_to_fs(t, dst) }) .for_each(|res| { if let Err(e) = res { error!("{}", e); } }); - + } else { info!("no template found. deploy finished"); } let symlink_dst = if early { - self.get_decrypt_dir_path_for_user() + self.decrypted_dir_for_user() } else { - self.get_decrypt_dir_path() + self.decrypted_dir() }; info!( "link decrypted dir {} to {}", target_extract_dir_with_gen.display(), - symlink_dst.as_str() + symlink_dst ); - match std::fs::remove_file(&symlink_dst) { + match std::fs::remove_file(symlink_dst) { Err(e) if e.kind() == io::ErrorKind::NotFound => {} Err(e) => Err(eyre!("{}", e))?, Ok(_) => { diff --git a/src/helper/secret_buf.rs b/src/helper/secret_buf.rs index 13f2a34..79c3363 100644 --- a/src/helper/secret_buf.rs +++ b/src/helper/secret_buf.rs @@ -1,3 +1,7 @@ +use std::fs::{OpenOptions, Permissions}; +use std::io::Write; +use std::os::unix::fs::PermissionsExt; +use std::path::PathBuf; use std::rc::Rc; use std::{io::Read, iter, marker::PhantomData}; @@ -38,13 +42,13 @@ impl SecBuf { let buffer = self.buf_ref(); let decryptor = age::Decryptor::new(&buffer[..])?; - let mut dec_ctx = vec![]; + let mut dec_content = vec![]; let mut reader = decryptor.decrypt(iter::once(ident))?; - let res = reader.read_to_end(&mut dec_ctx); + let res = reader.read_to_end(&mut dec_content); if let Ok(b) = res { debug!("decrypted secret {} bytes", b); } - Ok(SecBuf::new(dec_ctx)) + Ok(SecBuf::new(dec_content)) } } @@ -68,6 +72,8 @@ impl SecBuf { } use eyre::eyre; +use super::set_owner_group; + impl SecBuf { /// encrypt with host pub key, ssh key pub fn encrypt(self, recips: Vec>) -> Result> { @@ -76,14 +82,40 @@ impl SecBuf { .map_err(|_| eyre!("create encryptor err"))?; let buf = self.buf_ref(); - let mut enc_ctx = vec![]; + let mut enc_content = vec![]; - let mut writer = encryptor.wrap_output(&mut enc_ctx)?; + let mut writer = encryptor.wrap_output(&mut enc_content)?; use std::io::Write; writer.write_all(buf)?; writer.finish()?; - Ok(SecBuf::new(enc_ctx)) + Ok(SecBuf::new(enc_content)) + } + + pub fn deploy_to_fs( + &self, + item: impl crate::profile::DeployFactor, + dst: PathBuf, + ) -> Result<()> { + let mut the_file = { + let mode = crate::parser::parse_octal_str(item.mode()) + .map_err(|e| eyre!("parse octal permission err: {}", e))?; + let permissions = Permissions::from_mode(mode); + + let file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(dst)?; + + file.set_permissions(permissions)?; + + set_owner_group::set_owner_and_group(&file, item.owner(), item.group())?; + + file + }; + the_file.write_all(self.buf_ref())?; + Ok(()) } } diff --git a/src/helper/stored.rs b/src/helper/stored.rs index 11dbc90..8b16185 100644 --- a/src/helper/stored.rs +++ b/src/helper/stored.rs @@ -182,7 +182,7 @@ impl<'a> SecMap<'a, SecPBWith> { } /// read secret file - pub fn bake_ctx(self) -> Result>> { + pub fn bake(self) -> Result>> { self.inner() .into_iter() .map(|(k, v)| v.read_buffer().map(|b| (k, SecBuf::from(b)))) @@ -261,11 +261,11 @@ impl SecMap<'_, UniPath> { use std::io::Write; trace!("re-encrypted output path {}", real.path.display()); - let enc_ctx = store.read_buffer().expect("read buffer in store err"); + let enc = store.read_buffer().expect("read buffer in store err"); // rencrypt - let renc_ctx = SecBuf::::new(enc_ctx) + let agenc = SecBuf::::new(enc) .renc(ident, recips.clone()) - .expect("renc_ctx err"); + .expect("renc err"); let mut target_file = fs::OpenOptions::new() .write(true) @@ -274,7 +274,7 @@ impl SecMap<'_, UniPath> { .open(real.path.clone())?; target_file - .write_all(renc_ctx.buf_ref()) + .write_all(agenc.buf_ref()) .wrap_err_with(|| eyre!("write renc file error")) }) }