Skip to content

Commit

Permalink
+
Browse files Browse the repository at this point in the history
  • Loading branch information
oluceps committed Nov 2, 2024
1 parent c47ce39 commit 6e283c6
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 135 deletions.
147 changes: 44 additions & 103 deletions src/cmd/renc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use blake3::Hasher;
use eyre::{eyre, ContextCompat, Result};
use spdlog::{debug, error, info, trace};
use std::{
collections::HashMap,
fs::{self, File},
io::{Read, Write},
iter,
Expand All @@ -9,14 +11,13 @@ use std::{
};

use crate::{
cmd::stored_sec_path::{SecretBufferMap, SecretPathMap},
profile::{MasterIdentity, Profile, Settings},
cmd::stored_sec_path::{HashWithCtx, InCfg, SecMap, SecPath},
profile::{MasterIdentity, Profile},
};
use crate::{interop::add_to_store, profile};

use age::{x25519, Identity};

use super::stored_sec_path::StoredSecretPath;
use crate::helper::parse_identity::ParsedIdentity;
impl Profile {
pub fn get_key_pair_iter<'a>(&'a self) -> impl Iterator<Item = Result<ParsedIdentity>> + 'a {
Expand Down Expand Up @@ -56,15 +57,18 @@ impl Profile {
let renc_path = {
let mut p = flake_root.clone();
p.push(self.settings.storage_dir_relative.clone());
let p = p.canonicalize()?;
info!(
"reading user identity encrypted dir under flake root: {}",
p.display()
);
p
};

// from secrets metadata, read real config store
let sec_buf: SecretBufferMap = SecretPathMap::from_secret_set(&self.secrets).into();
// from secrets metadata, from real config store
let data = SecMap::<SecPath<_, InCfg>>::from(self.secrets.clone(), renc_path.clone());

let data_renc_path_map = data.clone().calc_renc(self.settings.host_pubkey.clone())?;

let decrypt = |buffer: &Vec<u8>, key: &dyn Identity| -> Result<Vec<u8>> {
let decryptor = age::Decryptor::new(&buffer[..])?;
Expand All @@ -79,110 +83,47 @@ impl Profile {
Ok(decrypted)
};

// WARN: this failed while using plugin
let avail_ident = if let Some(found) = key_pair_list.find(|k| k.is_ok()) {
if let Ok(r) = found {
r
} else {
return Err(eyre!("no available key for this material"));
}
} else {
return Err(eyre!("provided identities not valid"));
};

let key = avail_ident.get_identity();
let sec_buf = sec_buf.inner();
let decrypted_iter = sec_buf.iter().filter_map(|(s, b)| {
let decrypted = decrypt(b, &**key);
Some((s, decrypted))
});

let recip_host_pubkey = ssh::Recipient::from_str(self.settings.host_pubkey.as_str());

let recip_unwrap = recip_host_pubkey.unwrap();

let encrypted_iter = decrypted_iter.filter_map(|(s, b)| {
let m = SecretPathMap::from_profile(&self)
.to_flake_repo_relative_renced_path(&self, flake_root.clone());
let buffer = if let Err(e) = b {
error!("{}", e);
return None;
} else {
b.expect("there")
};

let b_hash = blake3::hash(&buffer);

if let Some(o) = m.inner().get(s) {
let flake_renc = fs::read(o.clone().inner());
if let Ok(c) = flake_renc {
let ctx = {
let decryptor = age::Decryptor::new(&c[..]).expect("");

let mut decrypted = vec![];
let mut reader = decryptor
.decrypt(iter::once(
&self
.settings
.host_keys // TODO: cannot compare on remote machine
.get(0)
.unwrap()
.get_identity()
.unwrap() as &dyn age::Identity,
))
.expect("decrypt fail");
let res = reader.read_to_end(&mut decrypted);
if let Ok(b) = res {
debug!("decrypted secret in store: {} bytes", b);
}

decrypted
};
trace!("checking hash{:?}", c);

let c_hash = blake3::hash(&ctx);
trace!("hash: prev {} after {}", c_hash, b_hash);
if c_hash == b_hash {
// skip
info!("skip unchanged file: {}", s.name);
return None;
}
}
}
let parsed_ident = key_pair_list
.find(|k| k.is_ok())
.wrap_err_with(|| eyre!("available keypair not found"))??;

let encryptor = age::Encryptor::with_recipients(iter::once(&recip_unwrap as _))
.expect("a recipient");
let mut out_buf = vec![];
let key = parsed_ident.get_identity();

let mut writer = encryptor.wrap_output(&mut out_buf).unwrap();
let sec_need_renc = data_renc_path_map
.inner()
.into_iter()
.filter(|(k, v)| {
let hash = v.get_hash();
let renc_path = {
let mut path = renc_path.clone();
path.push(hash.to_string());
path.canonicalize().expect("no err")
};

writer.write_all(&buffer[..]).unwrap();
writer.finish().unwrap();
debug!("comparing {}", renc_path.display());

Some((s, out_buf))
});
let exs = renc_path.exists();

trace!("re encrypted: {:?}", encrypted_iter);

info!("cleaning old re-encryption extract dir");
let ren = SecretPathMap::from_profile(&self).inner();
encrypted_iter.for_each(|(s, b)| {
let mut to_create = renc_path.clone();

let renced_store_path = ren.get(s).cloned().unwrap().inner();
to_create.push(renced_store_path.file_name().unwrap());

debug!("path string {:?}", to_create);
let mut fd = File::create(to_create).expect("create file error");
let _ = fd.write_all(&b[..]);
});
if exs {
info!("skipping {} since exist", k.id)
}

let o = add_to_store(renc_path)?;
if !o.status.success() {
error!("Command executed with failing error code");
}
// Another side, calculate with nix `builtins.path` and pass to when deploy as `storage`
info!("path added to store: {}", String::from_utf8(o.stdout)?);
!exs
})
.collect::<HashMap<profile::Secret, HashWithCtx>>()
.into_keys()
.collect::<Vec<profile::Secret>>();

// data.bake().and_then(|b| {
// b.inner().into_iter().filter(|(s,_)| sec_need_renc.contains(s)).for_each(|(k,v)|)
// })

// let o = add_to_store(renc_path)?;
// if !o.status.success() {
// error!("Command executed with failing error code");
// }
// // Another side, calculate with nix `builtins.path` and pass to when deploy as `storage`
// info!("path added to store: {}", String::from_utf8(o.stdout)?);
Ok(())
}
}
Loading

0 comments on commit 6e283c6

Please sign in to comment.