git.delta.rocks / jrsonnet / refs/commits / 5fd92ba91a91

difftreelog

feat non-shared secrets

Yaroslav Bolyukin2021-10-01parent: #076f1fe.patch.diff
in: trunk

2 files changed

modifiedcmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -1,6 +1,12 @@
-use crate::{fleetdata::FleetSecret, host::Config};
+use crate::{
+	fleetdata::{FleetSecret, FleetSharedSecret},
+	host::Config,
+};
 use anyhow::{bail, Result};
-use std::io::{self, Cursor, Read};
+use std::{
+	io::{self, Cursor, Read},
+	path::PathBuf,
+};
 use structopt::StructOpt;
 
 #[derive(StructOpt)]
@@ -8,7 +14,7 @@
 	/// Force load keys for all defined hosts
 	ForceKeys,
 	/// Add secret, data should be provided in stdin
-	Add {
+	AddShared {
 		/// Secret name
 		name: String,
 		/// Secret owners
@@ -18,7 +24,23 @@
 		force: bool,
 		#[structopt(long)]
 		public: Option<String>,
+		#[structopt(long)]
+		public_file: Option<PathBuf>,
 	},
+	/// Add secret, data should be provided in stdin
+	Add {
+		/// Secret name
+		name: String,
+		/// Secret owners
+		machine: String,
+		/// Override secret if already present
+		#[structopt(long)]
+		force: bool,
+		#[structopt(long)]
+		public: Option<String>,
+		#[structopt(long)]
+		public_file: Option<PathBuf>,
+	},
 }
 
 impl Secrets {
@@ -32,11 +54,12 @@
 					config.key(&host)?;
 				}
 			}
-			Secrets::Add {
+			Secrets::AddShared {
 				machines,
 				name,
 				force,
 				public,
+				public_file,
 			} => {
 				let recipients = machines
 					.iter()
@@ -61,16 +84,66 @@
 				};
 
 				let mut data = config.data_mut();
-				if data.secrets.contains_key(&name) && !force {
+				if data.shared_secrets.contains_key(&name) && !force {
 					bail!("secret already defined");
 				}
-				data.secrets.insert(
+				data.shared_secrets.insert(
 					name,
-					FleetSecret {
+					FleetSharedSecret {
 						owners: machines,
+						secret: FleetSecret {
+							expire_at: None,
+							secret,
+							public: match (public, public_file) {
+								(Some(v), None) => Some(v),
+								(None, Some(v)) => Some(std::fs::read_to_string(&v)?),
+								(Some(_), Some(_)) => {
+									bail!("only public or public_file should be set")
+								}
+								(None, None) => None,
+							},
+						},
+					},
+				);
+			}
+			Secrets::Add {
+				machine,
+				name,
+				force,
+				public,
+				public_file,
+			} => {
+				let recipient = config.recipient(&machine)?;
+
+				let secret = {
+					let mut input = vec![];
+					io::stdin().read_to_end(&mut input)?;
+
+					let mut encrypted = vec![];
+					let recipient = Box::new(recipient) as Box<dyn age::Recipient>;
+					let mut encryptor = age::Encryptor::with_recipients(vec![recipient])
+						.wrap_output(&mut encrypted)?;
+					io::copy(&mut Cursor::new(input), &mut encryptor)?;
+					encryptor.finish()?;
+					encrypted
+				};
+
+				let mut data = config.data_mut();
+				let host_secrets = data.host_secrets.entry(machine).or_default();
+				if host_secrets.contains_key(&name) && !force {
+					bail!("secret already defined");
+				}
+				host_secrets.insert(
+					name,
+					FleetSecret {
 						expire_at: None,
 						secret,
-						public,
+						public: match (public, public_file) {
+							(Some(v), None) => Some(v),
+							(None, Some(v)) => Some(std::fs::read_to_string(&v)?),
+							(Some(_), Some(_)) => bail!("only public or public_file should be set"),
+							(None, None) => None,
+						},
 					},
 				);
 			}
modifiedcmds/fleet/src/fleetdata.rsdiffbeforeafterboth
11}11}
1212
13#[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}
25
26#[derive(Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct FleetSharedSecret {
29 pub owners: Vec<String>,
30 #[serde(flatten)]
31 pub secret: FleetSecret,
32}
2133
22#[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>>,