difftreelog
feat non-shared secrets
in: trunk
2 files changed
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth1use crate::{fleetdata::FleetSecret, host::Config};2use anyhow::{bail, Result};3use std::io::{self, Cursor, Read};4use structopt::StructOpt;56#[derive(StructOpt)]7pub enum Secrets {8 /// Force load keys for all defined hosts9 ForceKeys,10 /// Add secret, data should be provided in stdin11 Add {12 /// Secret name13 name: String,14 /// Secret owners15 machines: Vec<String>,16 /// Override secret if already present17 #[structopt(long)]18 force: bool,19 #[structopt(long)]20 public: Option<String>,21 },22}2324impl Secrets {25 pub fn run(self, config: &Config) -> Result<()> {26 match self {27 Secrets::ForceKeys => {28 for host in config.list_hosts()? {29 if config.should_skip(&host) {30 continue;31 }32 config.key(&host)?;33 }34 }35 Secrets::Add {36 machines,37 name,38 force,39 public,40 } => {41 let recipients = machines42 .iter()43 .map(|m| config.recipient(m))44 .collect::<Result<Vec<_>>>()?;4546 let secret = {47 let mut input = vec![];48 io::stdin().read_to_end(&mut input)?;4950 let mut encrypted = vec![];51 let recipients = recipients52 .iter()53 .cloned()54 .map(|r| Box::new(r) as Box<dyn age::Recipient>)55 .collect();56 let mut encryptor =57 age::Encryptor::with_recipients(recipients).wrap_output(&mut encrypted)?;58 io::copy(&mut Cursor::new(input), &mut encryptor)?;59 encryptor.finish()?;60 encrypted61 };6263 let mut data = config.data_mut();64 if data.secrets.contains_key(&name) && !force {65 bail!("secret already defined");66 }67 data.secrets.insert(68 name,69 FleetSecret {70 owners: machines,71 expire_at: None,72 secret,73 public,74 },75 );76 }77 }78 Ok(())79 }80}cmds/fleet/src/fleetdata.rsdiffbeforeafterboth--- a/cmds/fleet/src/fleetdata.rs
+++ b/cmds/fleet/src/fleetdata.rs
@@ -11,18 +11,29 @@
}
#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
pub struct FleetData {
#[serde(default)]
pub hosts: BTreeMap<String, HostData>,
#[serde(default)]
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
- pub secrets: BTreeMap<String, FleetSecret>,
+ pub shared_secrets: BTreeMap<String, FleetSharedSecret>,
+ #[serde(default)]
+ #[serde(skip_serializing_if = "BTreeMap::is_empty")]
+ pub host_secrets: BTreeMap<String, BTreeMap<String, FleetSecret>>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
-pub struct FleetSecret {
+pub struct FleetSharedSecret {
pub owners: Vec<String>,
+ #[serde(flatten)]
+ pub secret: FleetSecret,
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FleetSecret {
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub expire_at: Option<DateTime<Utc>>,