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

difftreelog

feat rework secret add command

Yaroslav Bolyukin2021-09-18parent: #eae9921.patch.diff
in: trunk

1 file changed

modifiedsrc/cmds/secrets/mod.rsdiffbeforeafterboth
1use std::io::Write;1use crate::{fleetdata::FleetSecret, host::Config};
2
3use anyhow::Result;2use anyhow::{bail, Result};
4use clap::Clap;3use clap::Clap;
5
6use crate::host::Config;4use std::{
5 collections::BTreeMap,
6 io::{Cursor, Read},
7};
78
8#[derive(Clap)]9#[derive(Clap)]
9pub enum Secrets {10pub enum Secrets {
10 /// Force load keys for all defined hosts11 /// Force load keys for all defined hosts
11 ForceKeys,12 ForceKeys,
12 /// Add secret, data should be provided in stdin13 /// Add secret, data should be provided in stdin
13 Add {14 Add {
14 /// Secret owner15 /// Secret name
15 machine: String,16 name: String,
16 /// Secret name17 /// Secret owners
17 name: String,18 machines: Vec<String>,
19 /// Override secret if already present
20 #[clap(long)]
21 force: bool,
18 },22 },
19}23}
2024
29 config.key(&host)?;33 config.key(&host)?;
30 }34 }
31 }35 }
32 Secrets::Add { machine, name } => {36 Secrets::Add {
37 machines,
38 name,
39 force,
40 } => {
33 let recipient = config.recipient(&machine)?;41 let recipients = machines
42 .iter()
43 .map(|m| config.recipient(&m))
44 .collect::<Result<Vec<_>>>()?;
45
34 let encryptor = age::Encryptor::with_recipients(vec![Box::new(recipient)]);46 let secret_data = {
35
36 let mut encrypted = vec![];47 let mut input = vec![];
37 {
38 let mut w = encryptor.wrap_output(&mut encrypted)?;48 std::io::stdin().read_to_end(&mut input)?;
3949
40 let stdin = std::io::stdin();50 let data: BTreeMap<String, String> = serde_json::from_slice(&input)?;
41 let mut lock = stdin.lock();51 let mut transformed_data: BTreeMap<String, String> = BTreeMap::new();
52 for (k, v) in data {
53 if k.ends_with("_pub") {
54 transformed_data.insert(k, v);
55 } else if k.ends_with("_secret") {
56 let mut encrypted = vec![];
57 let recipients = recipients
58 .iter()
59 .cloned()
60 .map(|r| Box::new(r) as Box<dyn age::Recipient>)
61 .collect();
62 let mut encryptor = age::Encryptor::with_recipients(recipients)
63 .wrap_output(&mut encrypted)?;
42 std::io::copy(&mut lock, &mut w)?;64 std::io::copy(&mut Cursor::new(v.as_bytes()), &mut encryptor)?;
65 drop(encryptor);
66
67 transformed_data.insert(k, ascii85::encode(&encrypted));
68 } else {
69 bail!("unknown key type: {:?}", k);
70 }
71 }
72 transformed_data
73 };
74
75 let mut data = config.data_mut();
43 w.flush()?;76 if data.secrets.contains_key(&name) && !force {
44 }77 bail!("secret already defined");
4578 }
46 config.update_secret(&machine, &name, &encrypted)79 data.secrets.insert(
80 name,
81 FleetSecret {
82 owners: machines.clone(),
83 expire_at: None,
84 data: secret_data,
85 },
86 );
47 }87 }
48 }88 }
49 Ok(())89 Ok(())