difftreelog
feat rework secret add command
in: trunk
1 file changed
src/cmds/secrets/mod.rsdiffbeforeafterboth1use std::io::Write;23use anyhow::Result;4use clap::Clap;56use crate::host::Config;78#[derive(Clap)]9pub enum Secrets {10 /// Force load keys for all defined hosts11 ForceKeys,12 /// Add secret, data should be provided in stdin13 Add {14 /// Secret owner15 machine: String,16 /// Secret name17 name: String,18 },19}2021impl Secrets {22 pub fn run(self, config: &Config) -> Result<()> {23 match self {24 Secrets::ForceKeys => {25 for host in config.list_hosts()? {26 if config.should_skip(&host) {27 continue;28 }29 config.key(&host)?;30 }31 }32 Secrets::Add { machine, name } => {33 let recipient = config.recipient(&machine)?;34 let encryptor = age::Encryptor::with_recipients(vec![Box::new(recipient)]);3536 let mut encrypted = vec![];37 {38 let mut w = encryptor.wrap_output(&mut encrypted)?;3940 let stdin = std::io::stdin();41 let mut lock = stdin.lock();42 std::io::copy(&mut lock, &mut w)?;43 w.flush()?;44 }4546 config.update_secret(&machine, &name, &encrypted)47 }48 }49 Ok(())50 }51}1use crate::{fleetdata::FleetSecret, host::Config};2use anyhow::{bail, Result};3use clap::Clap;4use std::{5 collections::BTreeMap,6 io::{Cursor, Read},7};89#[derive(Clap)]10pub enum Secrets {11 /// Force load keys for all defined hosts12 ForceKeys,13 /// Add secret, data should be provided in stdin14 Add {15 /// Secret name16 name: String,17 /// Secret owners18 machines: Vec<String>,19 /// Override secret if already present20 #[clap(long)]21 force: bool,22 },23}2425impl Secrets {26 pub fn run(self, config: &Config) -> Result<()> {27 match self {28 Secrets::ForceKeys => {29 for host in config.list_hosts()? {30 if config.should_skip(&host) {31 continue;32 }33 config.key(&host)?;34 }35 }36 Secrets::Add {37 machines,38 name,39 force,40 } => {41 let recipients = machines42 .iter()43 .map(|m| config.recipient(&m))44 .collect::<Result<Vec<_>>>()?;4546 let secret_data = {47 let mut input = vec![];48 std::io::stdin().read_to_end(&mut input)?;4950 let data: BTreeMap<String, String> = serde_json::from_slice(&input)?;51 let mut transformed_data: BTreeMap<String, String> = BTreeMap::new();52 for (k, v) in data {53 if k.ends_with("_pub") {54 transformed_data.insert(k, v);55 } else if k.ends_with("_secret") {56 let mut encrypted = vec![];57 let recipients = recipients58 .iter()59 .cloned()60 .map(|r| Box::new(r) as Box<dyn age::Recipient>)61 .collect();62 let mut encryptor = age::Encryptor::with_recipients(recipients)63 .wrap_output(&mut encrypted)?;64 std::io::copy(&mut Cursor::new(v.as_bytes()), &mut encryptor)?;65 drop(encryptor);6667 transformed_data.insert(k, ascii85::encode(&encrypted));68 } else {69 bail!("unknown key type: {:?}", k);70 }71 }72 transformed_data73 };7475 let mut data = config.data_mut();76 if data.secrets.contains_key(&name) && !force {77 bail!("secret already defined");78 }79 data.secrets.insert(80 name,81 FleetSecret {82 owners: machines.clone(),83 expire_at: None,84 data: secret_data,85 },86 );87 }88 }89 Ok(())90 }91}