1 use anyhow
::{bail, Error}
;
14 use pbs_api_types
::Fingerprint
;
15 use pbs_datastore
::Kdf
;
16 use pbs_datastore
::paperkey
::{PaperkeyFormat, generate_paper_key}
;
23 TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
27 config
::tape_encryption_keys
::{
29 complete_key_fingerprint
,
33 pub fn encryption_key_commands() -> CommandLineInterface
{
35 let cmd_def
= CliCommandMap
::new()
36 .insert("list", CliCommand
::new(&API_METHOD_LIST_KEYS
))
39 CliCommand
::new(&API_METHOD_CREATE_KEY
)
43 CliCommand
::new(&API_METHOD_CHANGE_PASSPHRASE
)
44 .arg_param(&["fingerprint"])
45 .completion_cb("fingerprint", complete_key_fingerprint
)
49 CliCommand
::new(&API_METHOD_SHOW_KEY
)
50 .arg_param(&["fingerprint"])
51 .completion_cb("fingerprint", complete_key_fingerprint
)
55 CliCommand
::new(&API_METHOD_PAPER_KEY
)
56 .arg_param(&["fingerprint"])
57 .completion_cb("fingerprint", complete_key_fingerprint
)
61 CliCommand
::new(&API_METHOD_RESTORE_KEY
)
65 CliCommand
::new(&api2
::config
::tape_encryption_keys
::API_METHOD_DELETE_KEY
)
66 .arg_param(&["fingerprint"])
67 .completion_cb("fingerprint", complete_key_fingerprint
)
78 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
81 description
: "Include the specified subject as title text.",
91 /// Generate a printable, human readable text file containing the encryption key.
93 /// This also includes a scanable QR code for fast key restore.
95 fingerprint
: Fingerprint
,
96 subject
: Option
<String
>,
97 output_format
: Option
<PaperkeyFormat
>,
98 ) -> Result
<(), Error
> {
100 let (config_map
, _digest
) = load_key_configs()?
;
102 let key_config
= match config_map
.get(&fingerprint
) {
103 Some(key_config
) => key_config
,
104 None
=> bail
!("tape encryption key '{}' does not exist.", fingerprint
),
107 let data
: String
= serde_json
::to_string_pretty(&key_config
)?
;
109 generate_paper_key(std
::io
::stdout(), &data
, subject
, output_format
)
116 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
119 schema
: OUTPUT_FORMAT
,
125 /// Print the encryption key's metadata.
128 rpcenv
: &mut dyn RpcEnvironment
,
129 ) -> Result
<(), Error
> {
131 let output_format
= get_output_format(¶m
);
133 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_READ_KEY
;
134 let mut data
= match info
.handler
{
135 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
139 let options
= proxmox
::api
::cli
::default_table_format_options()
140 .column(ColumnConfig
::new("kdf"))
141 .column(ColumnConfig
::new("created").renderer(pbs_tools
::format
::render_epoch
))
142 .column(ColumnConfig
::new("modified").renderer(pbs_tools
::format
::render_epoch
))
143 .column(ColumnConfig
::new("fingerprint"))
144 .column(ColumnConfig
::new("hint"));
146 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
159 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
162 schema
: PASSWORD_HINT_SCHEMA
,
168 /// Change the encryption key's password.
169 fn change_passphrase(
171 rpcenv
: &mut dyn RpcEnvironment
,
172 ) -> Result
<(), Error
> {
174 if !tty
::stdin_isatty() {
175 bail
!("unable to change passphrase - no tty");
178 let password
= tty
::read_password("Current Tape Encryption Key Password: ")?
;
180 let new_password
= tty
::read_and_verify_password("New Tape Encryption Key Password: ")?
;
182 param
["password"] = String
::from_utf8(password
)?
.into();
183 param
["new-password"] = String
::from_utf8(new_password
)?
.into();
185 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_CHANGE_PASSPHRASE
;
187 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
198 schema
: DRIVE_NAME_SCHEMA
,
204 /// Restore encryption key from tape (read password from stdin)
205 async
fn restore_key(
207 rpcenv
: &mut dyn RpcEnvironment
,
208 ) -> Result
<(), Error
> {
210 let (config
, _digest
) = pbs_config
::drive
::config()?
;
211 param
["drive"] = crate::extract_drive_name(&mut param
, &config
)?
.into();
213 if !tty
::stdin_isatty() {
214 bail
!("no password input mechanism available");
217 let password
= tty
::read_password("Tepe Encryption Key Password: ")?
;
218 param
["password"] = String
::from_utf8(password
)?
.into();
220 let info
= &api2
::tape
::drive
::API_METHOD_RESTORE_KEY
;
222 ApiHandler
::Async(handler
) => (handler
)(param
, info
, rpcenv
).await?
,
237 description
: "Password restore hint.",
245 /// Create key (read password from stdin)
248 rpcenv
: &mut dyn RpcEnvironment
,
249 ) -> Result
<(), Error
> {
251 if !tty
::stdin_isatty() {
252 bail
!("no password input mechanism available");
255 let password
= tty
::read_and_verify_password("Tape Encryption Key Password: ")?
;
257 param
["password"] = String
::from_utf8(password
)?
.into();
259 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_CREATE_KEY
;
260 let fingerprint
= match info
.handler
{
261 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
265 println
!("{}", fingerprint
);
275 schema
: OUTPUT_FORMAT
,
284 rpcenv
: &mut dyn RpcEnvironment
,
285 ) -> Result
<(), Error
> {
287 let output_format
= get_output_format(¶m
);
288 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_LIST_KEYS
;
289 let mut data
= match info
.handler
{
290 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
294 let options
= default_table_format_options()
295 .column(ColumnConfig
::new("fingerprint"))
296 .column(ColumnConfig
::new("hint"))
299 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);