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
1use 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;
511
6#[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 hosts
9 ForceKeys,15 ForceKeys,
10 /// Add secret, data should be provided in stdin16 /// Add secret, data should be provided in stdin
11 Add {17 AddShared {
12 /// Secret name18 /// Secret name
13 name: String,19 name: String,
14 /// Secret owners20 /// Secret owners
18 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 stdin
31 Add {
32 /// Secret name
33 name: String,
34 /// Secret owners
35 machine: String,
36 /// Override secret if already present
37 #[structopt(long)]
38 force: bool,
39 #[structopt(long)]
40 public: Option<String>,
41 #[structopt(long)]
42 public_file: Option<PathBuf>,
43 },
22}44}
2345
24impl 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 = machines
42 .iter()65 .iter()
61 };84 };
6285
63 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)?;
117
118 let secret = {
119 let mut input = vec![];
120 io::stdin().read_to_end(&mut input)?;
121
122 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 encrypted
129 };
130
131 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 }
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>>,