git.delta.rocks / jrsonnet / refs/commits / 41ecf404fcd9

difftreelog

source

cmds/fleet/src/cmds/secrets/mod.rs3.7 KiBsourcehistory
1use crate::{2	fleetdata::{FleetSecret, FleetSharedSecret},3	host::Config,4};5use anyhow::{bail, Result};6use futures::{StreamExt, TryStreamExt};7use std::{8	io::{self, Cursor, Read},9	path::PathBuf,10};11use structopt::StructOpt;1213#[derive(StructOpt)]14pub enum Secrets {15	/// Force load keys for all defined hosts16	ForceKeys,17	/// Add secret, data should be provided in stdin18	AddShared {19		/// Secret name20		name: String,21		/// Secret owners22		machines: Vec<String>,23		/// Override secret if already present24		#[structopt(long)]25		force: bool,26		#[structopt(long)]27		public: Option<String>,28		#[structopt(long)]29		public_file: Option<PathBuf>,30	},31	/// Add secret, data should be provided in stdin32	Add {33		/// Secret name34		name: String,35		/// Secret owners36		machine: String,37		/// Override secret if already present38		#[structopt(long)]39		force: bool,40		#[structopt(long)]41		public: Option<String>,42		#[structopt(long)]43		public_file: Option<PathBuf>,44	},45}4647impl Secrets {48	pub async fn run(self, config: &Config) -> Result<()> {49		match self {50			Secrets::ForceKeys => {51				for host in config.list_hosts().await? {52					if config.should_skip(&host) {53						continue;54					}55					config.key(&host).await?;56				}57			}58			Secrets::AddShared {59				machines,60				name,61				force,62				public,63				public_file,64			} => {65				let recipients = futures::stream::iter(machines.iter())66					.then(|m| config.recipient(m))67					.try_collect::<Vec<_>>()68					.await?;6970				let secret = {71					let mut input = vec![];72					io::stdin().read_to_end(&mut input)?;7374					if input.is_empty() {75						input76					} else {77						let mut encrypted = vec![];78						let recipients = recipients79							.iter()80							.cloned()81							.map(|r| Box::new(r) as Box<dyn age::Recipient>)82							.collect();83						let mut encryptor = age::Encryptor::with_recipients(recipients)84							.wrap_output(&mut encrypted)?;85						io::copy(&mut Cursor::new(input), &mut encryptor)?;86						encryptor.finish()?;87						encrypted88					}89				};9091				let mut data = config.data_mut();92				if data.shared_secrets.contains_key(&name) && !force {93					bail!("secret already defined");94				}95				data.shared_secrets.insert(96					name,97					FleetSharedSecret {98						owners: machines,99						secret: FleetSecret {100							expire_at: None,101							secret,102							public: match (public, public_file) {103								(Some(v), None) => Some(v),104								(None, Some(v)) => Some(std::fs::read_to_string(&v)?),105								(Some(_), Some(_)) => {106									bail!("only public or public_file should be set")107								}108								(None, None) => None,109							},110						},111					},112				);113			}114			Secrets::Add {115				machine,116				name,117				force,118				public,119				public_file,120			} => {121				let recipient = config.recipient(&machine).await?;122123				let secret = {124					let mut input = vec![];125					io::stdin().read_to_end(&mut input)?;126127					let mut encrypted = vec![];128					let recipient = Box::new(recipient) as Box<dyn age::Recipient>;129					let mut encryptor = age::Encryptor::with_recipients(vec![recipient])130						.wrap_output(&mut encrypted)?;131					io::copy(&mut Cursor::new(input), &mut encryptor)?;132					encryptor.finish()?;133					encrypted134				};135136				let mut data = config.data_mut();137				let host_secrets = data.host_secrets.entry(machine).or_default();138				if host_secrets.contains_key(&name) && !force {139					bail!("secret already defined");140				}141				host_secrets.insert(142					name,143					FleetSecret {144						expire_at: None,145						secret,146						public: match (public, public_file) {147							(Some(v), None) => Some(v),148							(None, Some(v)) => Some(std::fs::read_to_string(&v)?),149							(Some(_), Some(_)) => bail!("only public or public_file should be set"),150							(None, None) => None,151						},152					},153				);154			}155		}156		Ok(())157	}158}