1 /// Helper to run tape commands as root. Currently only required
2 /// to read and set the encryption key.
4 /// This command can use STDIN as tape device handle.
7 use std
::os
::unix
::io
::{AsRawFd, FromRawFd}
;
9 use anyhow
::{bail, Error}
;
10 use serde_json
::Value
;
12 use proxmox_router
::{cli::*, RpcEnvironment}
;
13 use proxmox_schema
::api
;
14 use proxmox_uuid
::Uuid
;
17 Fingerprint
, LTO_DRIVE_PATH_SCHEMA
, DRIVE_NAME_SCHEMA
, TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
18 MEDIA_SET_UUID_SCHEMA
, LtoTapeDrive
,
21 use pbs_tape
::linux_list_drives
::{open_lto_tape_device, check_tape_is_lto_tape_device}
;
33 fn get_tape_handle(param
: &Value
) -> Result
<LtoTapeHandle
, Error
> {
35 let handle
= if let Some(name
) = param
["drive"].as_str() {
36 let (config
, _digest
) = pbs_config
::drive
::config()?
;
37 let drive
: LtoTapeDrive
= config
.lookup("lto", name
)?
;
38 eprintln
!("using device {}", drive
.path
);
39 open_lto_tape_drive(&drive
)?
40 } else if let Some(device
) = param
["device"].as_str() {
41 eprintln
!("using device {}", device
);
42 LtoTapeHandle
::new(open_lto_tape_device(device
)?
)?
43 } else if let Some(true) = param
["stdin"].as_bool() {
44 eprintln
!("using stdin");
45 let fd
= std
::io
::stdin().as_raw_fd();
46 let file
= unsafe { File::from_raw_fd(fd) }
;
47 check_tape_is_lto_tape_device(&file
)?
;
48 LtoTapeHandle
::new(file
)?
49 } else if let Ok(name
) = std
::env
::var("PROXMOX_TAPE_DRIVE") {
50 let (config
, _digest
) = pbs_config
::drive
::config()?
;
51 let drive
: LtoTapeDrive
= config
.lookup("lto", &name
)?
;
52 eprintln
!("using device {}", drive
.path
);
53 open_lto_tape_drive(&drive
)?
55 let (config
, _digest
) = pbs_config
::drive
::config()?
;
57 let mut drive_names
= Vec
::new();
58 for (name
, (section_type
, _
)) in config
.sections
.iter() {
59 if section_type
!= "lto" { continue; }
60 drive_names
.push(name
);
63 if drive_names
.len() == 1 {
64 let name
= drive_names
[0];
65 let drive
: LtoTapeDrive
= config
.lookup("lto", name
)?
;
66 eprintln
!("using device {}", drive
.path
);
67 open_lto_tape_drive(&drive
)?
69 bail
!("no drive/device specified");
80 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
84 schema
: MEDIA_SET_UUID_SCHEMA
,
88 schema
: DRIVE_NAME_SCHEMA
,
92 schema
: LTO_DRIVE_PATH_SCHEMA
,
96 description
: "Use standard input as device handle.",
103 /// Set or clear encryption key
105 fingerprint
: Option
<Fingerprint
>,
108 ) -> Result
<(), Error
> {
110 let result
= proxmox_lang
::try_block
!({
111 let mut handle
= get_tape_handle(¶m
)?
;
113 match (fingerprint
, uuid
) {
114 (Some(fingerprint
), Some(uuid
)) => {
115 handle
.set_encryption(Some((fingerprint
, uuid
)))?
;
118 bail
!("missing media set uuid");
121 handle
.set_encryption(None
)?
;
126 }).map_err(|err
: Error
| err
.to_string());
128 println
!("{}", serde_json
::to_string_pretty(&result
)?
);
133 fn main() -> Result
<(), Error
> {
135 // check if we are user root or backup
136 let backup_uid
= pbs_config
::backup_user()?
.uid
;
137 let backup_gid
= pbs_config
::backup_group()?
.gid
;
138 let running_uid
= nix
::unistd
::Uid
::current();
139 let running_gid
= nix
::unistd
::Gid
::current();
141 let effective_uid
= nix
::unistd
::Uid
::effective();
142 if !effective_uid
.is_root() {
143 bail
!("this program needs to be run with setuid root");
146 if !running_uid
.is_root() && (running_uid
!= backup_uid
|| running_gid
!= backup_gid
) {
148 "Not running as backup user or group (got uid {} gid {})",
149 running_uid
, running_gid
,
153 let cmd_def
= CliCommandMap
::new()
156 CliCommand
::new(&API_METHOD_SET_ENCRYPTION
)
160 let mut rpcenv
= CliEnvironment
::new();
161 rpcenv
.set_auth_id(Some(String
::from("root@pam")));
163 run_cli_command(cmd_def
, rpcenv
, None
);