]> git.proxmox.com Git - proxmox-backup.git/blob - src/bin/proxmox_tape/encryption_key.rs
e45f2552c0e991451f7be88cd698508802ee9ebb
[proxmox-backup.git] / src / bin / proxmox_tape / encryption_key.rs
1 use anyhow::{bail, Error};
2 use serde_json::Value;
3
4 use proxmox::{
5 api::{
6 api,
7 cli::*,
8 RpcEnvironment,
9 ApiHandler,
10 },
11 sys::linux::tty,
12 };
13
14 use proxmox_backup::{
15 tools,
16 config,
17 api2::{
18 self,
19 types::{
20 DRIVE_NAME_SCHEMA,
21 TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
22 PASSWORD_HINT_SCHEMA,
23 Kdf,
24 },
25 },
26 config::tape_encryption_keys::complete_key_fingerprint,
27 };
28
29 pub fn encryption_key_commands() -> CommandLineInterface {
30
31 let cmd_def = CliCommandMap::new()
32 .insert("list", CliCommand::new(&API_METHOD_LIST_KEYS))
33 .insert(
34 "create",
35 CliCommand::new(&API_METHOD_CREATE_KEY)
36 )
37 .insert(
38 "change-passphrase",
39 CliCommand::new(&API_METHOD_CHANGE_PASSPHRASE)
40 .arg_param(&["fingerprint"])
41 .completion_cb("fingerprint", complete_key_fingerprint)
42 )
43 .insert(
44 "show",
45 CliCommand::new(&API_METHOD_SHOW_KEY)
46 .arg_param(&["fingerprint"])
47 .completion_cb("fingerprint", complete_key_fingerprint)
48 )
49 .insert(
50 "restore",
51 CliCommand::new(&API_METHOD_RESTORE_KEY)
52 )
53 .insert(
54 "remove",
55 CliCommand::new(&api2::config::tape_encryption_keys::API_METHOD_DELETE_KEY)
56 .arg_param(&["fingerprint"])
57 .completion_cb("fingerprint", complete_key_fingerprint)
58 )
59 ;
60
61 cmd_def.into()
62 }
63
64 #[api(
65 input: {
66 properties: {
67 fingerprint: {
68 schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
69 },
70 "output-format": {
71 schema: OUTPUT_FORMAT,
72 optional: true,
73 },
74 },
75 },
76 )]
77 /// Print tthe encryption key's metadata.
78 fn show_key(
79 param: Value,
80 rpcenv: &mut dyn RpcEnvironment,
81 ) -> Result<(), Error> {
82
83 let output_format = get_output_format(&param);
84
85 let info = &api2::config::tape_encryption_keys::API_METHOD_READ_KEY;
86 let mut data = match info.handler {
87 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
88 _ => unreachable!(),
89 };
90
91 let options = proxmox::api::cli::default_table_format_options()
92 .column(ColumnConfig::new("kdf"))
93 .column(ColumnConfig::new("created").renderer(tools::format::render_epoch))
94 .column(ColumnConfig::new("modified").renderer(tools::format::render_epoch))
95 .column(ColumnConfig::new("fingerprint"))
96 .column(ColumnConfig::new("hint"));
97
98 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
99
100 Ok(())
101 }
102
103 #[api(
104 input: {
105 properties: {
106 kdf: {
107 type: Kdf,
108 optional: true,
109 },
110 fingerprint: {
111 schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
112 },
113 hint: {
114 schema: PASSWORD_HINT_SCHEMA,
115 optional: true,
116 },
117 },
118 },
119 )]
120 /// Change the encryption key's password.
121 fn change_passphrase(
122 mut param: Value,
123 rpcenv: &mut dyn RpcEnvironment,
124 ) -> Result<(), Error> {
125
126 if !tty::stdin_isatty() {
127 bail!("unable to change passphrase - no tty");
128 }
129
130 let password = tty::read_password("Current Tape Encryption Key Password: ")?;
131
132 let new_password = tty::read_and_verify_password("New Tape Encryption Key Password: ")?;
133
134 param["password"] = String::from_utf8(password)?.into();
135 param["new-password"] = String::from_utf8(new_password)?.into();
136
137 let info = &api2::config::tape_encryption_keys::API_METHOD_CHANGE_PASSPHRASE;
138 match info.handler {
139 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
140 _ => unreachable!(),
141 };
142
143 Ok(())
144 }
145
146 #[api(
147 input: {
148 properties: {
149 drive: {
150 schema: DRIVE_NAME_SCHEMA,
151 optional: true,
152 },
153 },
154 },
155 )]
156 /// Restore encryption key from tape (read password from stdin)
157 async fn restore_key(
158 mut param: Value,
159 rpcenv: &mut dyn RpcEnvironment,
160 ) -> Result<(), Error> {
161
162 let (config, _digest) = config::drive::config()?;
163 param["drive"] = crate::lookup_drive_name(&param, &config)?.into();
164
165 if !tty::stdin_isatty() {
166 bail!("no password input mechanism available");
167 }
168
169 let password = tty::read_password("Tepe Encryption Key Password: ")?;
170 param["password"] = String::from_utf8(password)?.into();
171
172 let info = &api2::tape::drive::API_METHOD_RESTORE_KEY;
173 match info.handler {
174 ApiHandler::Async(handler) => (handler)(param, info, rpcenv).await?,
175 _ => unreachable!(),
176 };
177
178 Ok(())
179 }
180
181 #[api(
182 input: {
183 properties: {
184 kdf: {
185 type: Kdf,
186 optional: true,
187 },
188 hint: {
189 description: "Password restore hint.",
190 type: String,
191 min_length: 1,
192 max_length: 32,
193 },
194 },
195 },
196 )]
197 /// Create key (read password from stdin)
198 fn create_key(
199 mut param: Value,
200 rpcenv: &mut dyn RpcEnvironment,
201 ) -> Result<(), Error> {
202
203 if !tty::stdin_isatty() {
204 bail!("no password input mechanism available");
205 }
206
207 let password = tty::read_and_verify_password("Tape Encryption Key Password: ")?;
208
209 param["password"] = String::from_utf8(password)?.into();
210
211 let info = &api2::config::tape_encryption_keys::API_METHOD_CREATE_KEY;
212 let fingerprint = match info.handler {
213 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
214 _ => unreachable!(),
215 };
216
217 println!("{}", fingerprint);
218
219 Ok(())
220 }
221
222
223 #[api(
224 input: {
225 properties: {
226 "output-format": {
227 schema: OUTPUT_FORMAT,
228 optional: true,
229 },
230 },
231 },
232 )]
233 /// List keys
234 fn list_keys(
235 param: Value,
236 rpcenv: &mut dyn RpcEnvironment,
237 ) -> Result<(), Error> {
238
239 let output_format = get_output_format(&param);
240 let info = &api2::config::tape_encryption_keys::API_METHOD_LIST_KEYS;
241 let mut data = match info.handler {
242 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
243 _ => unreachable!(),
244 };
245
246 let options = default_table_format_options()
247 .column(ColumnConfig::new("fingerprint"))
248 .column(ColumnConfig::new("hint"))
249 ;
250
251 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
252
253 Ok(())
254 }