1 use anyhow
::{bail, Error}
;
15 Fingerprint
, Kdf
, DRIVE_NAME_SCHEMA
, TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
19 use pbs_datastore
::paperkey
::{PaperkeyFormat, generate_paper_key}
;
20 use pbs_config
::tape_encryption_keys
::{load_key_configs,complete_key_fingerprint}
;
22 use proxmox_backup
::api2
;
24 pub fn encryption_key_commands() -> CommandLineInterface
{
26 let cmd_def
= CliCommandMap
::new()
27 .insert("list", CliCommand
::new(&API_METHOD_LIST_KEYS
))
30 CliCommand
::new(&API_METHOD_CREATE_KEY
)
34 CliCommand
::new(&API_METHOD_CHANGE_PASSPHRASE
)
35 .arg_param(&["fingerprint"])
36 .completion_cb("fingerprint", complete_key_fingerprint
)
40 CliCommand
::new(&API_METHOD_SHOW_KEY
)
41 .arg_param(&["fingerprint"])
42 .completion_cb("fingerprint", complete_key_fingerprint
)
46 CliCommand
::new(&API_METHOD_PAPER_KEY
)
47 .arg_param(&["fingerprint"])
48 .completion_cb("fingerprint", complete_key_fingerprint
)
52 CliCommand
::new(&API_METHOD_RESTORE_KEY
)
56 CliCommand
::new(&api2
::config
::tape_encryption_keys
::API_METHOD_DELETE_KEY
)
57 .arg_param(&["fingerprint"])
58 .completion_cb("fingerprint", complete_key_fingerprint
)
69 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
72 description
: "Include the specified subject as title text.",
82 /// Generate a printable, human readable text file containing the encryption key.
84 /// This also includes a scanable QR code for fast key restore.
86 fingerprint
: Fingerprint
,
87 subject
: Option
<String
>,
88 output_format
: Option
<PaperkeyFormat
>,
89 ) -> Result
<(), Error
> {
91 let (config_map
, _digest
) = load_key_configs()?
;
93 let key_config
= match config_map
.get(&fingerprint
) {
94 Some(key_config
) => key_config
,
95 None
=> bail
!("tape encryption key '{}' does not exist.", fingerprint
),
98 let data
: String
= serde_json
::to_string_pretty(&key_config
)?
;
100 generate_paper_key(std
::io
::stdout(), &data
, subject
, output_format
)
107 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
110 schema
: OUTPUT_FORMAT
,
116 /// Print the encryption key's metadata.
119 rpcenv
: &mut dyn RpcEnvironment
,
120 ) -> Result
<(), Error
> {
122 let output_format
= get_output_format(¶m
);
124 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_READ_KEY
;
125 let mut data
= match info
.handler
{
126 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
130 let options
= proxmox
::api
::cli
::default_table_format_options()
131 .column(ColumnConfig
::new("kdf"))
132 .column(ColumnConfig
::new("created").renderer(pbs_tools
::format
::render_epoch
))
133 .column(ColumnConfig
::new("modified").renderer(pbs_tools
::format
::render_epoch
))
134 .column(ColumnConfig
::new("fingerprint"))
135 .column(ColumnConfig
::new("hint"));
137 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
150 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
153 schema
: PASSWORD_HINT_SCHEMA
,
159 /// Change the encryption key's password.
160 fn change_passphrase(
162 rpcenv
: &mut dyn RpcEnvironment
,
163 ) -> Result
<(), Error
> {
165 if !tty
::stdin_isatty() {
166 bail
!("unable to change passphrase - no tty");
169 let password
= tty
::read_password("Current Tape Encryption Key Password: ")?
;
171 let new_password
= tty
::read_and_verify_password("New Tape Encryption Key Password: ")?
;
173 param
["password"] = String
::from_utf8(password
)?
.into();
174 param
["new-password"] = String
::from_utf8(new_password
)?
.into();
176 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_CHANGE_PASSPHRASE
;
178 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
189 schema
: DRIVE_NAME_SCHEMA
,
195 /// Restore encryption key from tape (read password from stdin)
196 async
fn restore_key(
198 rpcenv
: &mut dyn RpcEnvironment
,
199 ) -> Result
<(), Error
> {
201 let (config
, _digest
) = pbs_config
::drive
::config()?
;
202 param
["drive"] = crate::extract_drive_name(&mut param
, &config
)?
.into();
204 if !tty
::stdin_isatty() {
205 bail
!("no password input mechanism available");
208 let password
= tty
::read_password("Tepe Encryption Key Password: ")?
;
209 param
["password"] = String
::from_utf8(password
)?
.into();
211 let info
= &api2
::tape
::drive
::API_METHOD_RESTORE_KEY
;
213 ApiHandler
::Async(handler
) => (handler
)(param
, info
, rpcenv
).await?
,
228 description
: "Password restore hint.",
236 /// Create key (read password from stdin)
239 rpcenv
: &mut dyn RpcEnvironment
,
240 ) -> Result
<(), Error
> {
242 if !tty
::stdin_isatty() {
243 bail
!("no password input mechanism available");
246 let password
= tty
::read_and_verify_password("Tape Encryption Key Password: ")?
;
248 param
["password"] = String
::from_utf8(password
)?
.into();
250 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_CREATE_KEY
;
251 let fingerprint
= match info
.handler
{
252 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
256 println
!("{}", fingerprint
);
266 schema
: OUTPUT_FORMAT
,
275 rpcenv
: &mut dyn RpcEnvironment
,
276 ) -> Result
<(), Error
> {
278 let output_format
= get_output_format(¶m
);
279 let info
= &api2
::config
::tape_encryption_keys
::API_METHOD_LIST_KEYS
;
280 let mut data
= match info
.handler
{
281 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
285 let options
= default_table_format_options()
286 .column(ColumnConfig
::new("fingerprint"))
287 .column(ColumnConfig
::new("hint"))
290 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);