difftreelog
feat non-shared secrets
in: trunk
2 files changed
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth1use crate::{fleetdata::FleetSecret, host::Config};1use crate::{2 fleetdata::{FleetSecret, FleetSharedSecret},3 host::Config,4};2use anyhow::{bail, Result};5use anyhow::{bail, Result};3use std::io::{self, Cursor, Read};6use std::{7 io::{self, Cursor, Read},8 path::PathBuf,9};4use structopt::StructOpt;10use structopt::StructOpt;5116#[derive(StructOpt)]12#[derive(StructOpt)]7pub enum Secrets {13pub enum Secrets {8 /// Force load keys for all defined hosts14 /// Force load keys for all defined hosts9 ForceKeys,15 ForceKeys,10 /// Add secret, data should be provided in stdin16 /// Add secret, data should be provided in stdin11 Add {17 AddShared {12 /// Secret name18 /// Secret name13 name: String,19 name: String,14 /// Secret owners20 /// Secret owners18 force: bool,24 force: bool,19 #[structopt(long)]25 #[structopt(long)]20 public: Option<String>,26 public: Option<String>,27 #[structopt(long)]28 public_file: Option<PathBuf>,21 },29 },30 /// Add secret, data should be provided in stdin31 Add {32 /// Secret name33 name: String,34 /// Secret owners35 machine: String,36 /// Override secret if already present37 #[structopt(long)]38 force: bool,39 #[structopt(long)]40 public: Option<String>,41 #[structopt(long)]42 public_file: Option<PathBuf>,43 },22}44}234524impl Secrets {46impl Secrets {32 config.key(&host)?;54 config.key(&host)?;33 }55 }34 }56 }35 Secrets::Add {57 Secrets::AddShared {36 machines,58 machines,37 name,59 name,38 force,60 force,39 public,61 public,62 public_file,40 } => {63 } => {41 let recipients = machines64 let recipients = machines42 .iter()65 .iter()61 };84 };628563 let mut data = config.data_mut();86 let mut data = config.data_mut();64 if data.secrets.contains_key(&name) && !force {87 if data.shared_secrets.contains_key(&name) && !force {65 bail!("secret already defined");88 bail!("secret already defined");66 }89 }67 data.secrets.insert(90 data.shared_secrets.insert(68 name,91 name,69 FleetSecret {92 FleetSharedSecret {70 owners: machines,93 owners: machines,94 secret: FleetSecret {71 expire_at: None,95 expire_at: None,72 secret,96 secret,73 public,97 public: match (public, public_file) {98 (Some(v), None) => Some(v),99 (None, Some(v)) => Some(std::fs::read_to_string(&v)?),100 (Some(_), Some(_)) => {101 bail!("only public or public_file should be set")102 }103 (None, None) => None,104 },105 },74 },106 },75 );107 );76 }108 }109 Secrets::Add {110 machine,111 name,112 force,113 public,114 public_file,115 } => {116 let recipient = config.recipient(&machine)?;117118 let secret = {119 let mut input = vec![];120 io::stdin().read_to_end(&mut input)?;121122 let mut encrypted = vec![];123 let recipient = Box::new(recipient) as Box<dyn age::Recipient>;124 let mut encryptor = age::Encryptor::with_recipients(vec![recipient])125 .wrap_output(&mut encrypted)?;126 io::copy(&mut Cursor::new(input), &mut encryptor)?;127 encryptor.finish()?;128 encrypted129 };130131 let mut data = config.data_mut();132 let host_secrets = data.host_secrets.entry(machine).or_default();133 if host_secrets.contains_key(&name) && !force {134 bail!("secret already defined");135 }136 host_secrets.insert(137 name,138 FleetSecret {139 expire_at: None,140 secret,141 public: match (public, public_file) {142 (Some(v), None) => Some(v),143 (None, Some(v)) => Some(std::fs::read_to_string(&v)?),144 (Some(_), Some(_)) => bail!("only public or public_file should be set"),145 (None, None) => None,146 },147 },148 );149 }77 }150 }78 Ok(())151 Ok(())79 }152 }cmds/fleet/src/fleetdata.rsdiffbeforeafterboth11}11}121213#[derive(Serialize, Deserialize)]13#[derive(Serialize, Deserialize)]14#[serde(rename_all = "camelCase")]14pub struct FleetData {15pub struct FleetData {15 #[serde(default)]16 #[serde(default)]16 pub hosts: BTreeMap<String, HostData>,17 pub hosts: BTreeMap<String, HostData>,18 #[serde(default)]19 #[serde(skip_serializing_if = "BTreeMap::is_empty")]20 pub shared_secrets: BTreeMap<String, FleetSharedSecret>,17 #[serde(default)]21 #[serde(default)]18 #[serde(skip_serializing_if = "BTreeMap::is_empty")]22 #[serde(skip_serializing_if = "BTreeMap::is_empty")]19 pub secrets: BTreeMap<String, FleetSecret>,23 pub host_secrets: BTreeMap<String, BTreeMap<String, FleetSecret>>,20}24}2526#[derive(Serialize, Deserialize)]27#[serde(rename_all = "camelCase")]28pub struct FleetSharedSecret {29 pub owners: Vec<String>,30 #[serde(flatten)]31 pub secret: FleetSecret,32}213322#[derive(Serialize, Deserialize)]34#[derive(Serialize, Deserialize)]23#[serde(rename_all = "camelCase")]35#[serde(rename_all = "camelCase")]24pub struct FleetSecret {36pub struct FleetSecret {25 pub owners: Vec<String>,26 #[serde(default)]37 #[serde(default)]27 #[serde(skip_serializing_if = "Option::is_none")]38 #[serde(skip_serializing_if = "Option::is_none")]28 pub expire_at: Option<DateTime<Utc>>,39 pub expire_at: Option<DateTime<Utc>>,