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 14
9 ForceKeys,15 ForceKeys,
10 16
11 Add {17 AddShared {
12 18
13 name: String,19 name: String,
14 20
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
31 Add {
32
33 name: String,
34
35 machine: String,
36
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 {
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 }