diff --git a/src/api2/config/changer.rs b/src/api2/config/changer.rs index a40939fd..86ebda5f 100644 --- a/src/api2/config/changer.rs +++ b/src/api2/config/changer.rs @@ -6,12 +6,21 @@ use proxmox::api::{ api, Router, RpcEnvironment, + Permission, schema::parse_property_string, }; use crate::{ - config, + config::{ + self, + cached_user_info::CachedUserInfo, + acl::{ + PRIV_TAPE_AUDIT, + PRIV_TAPE_MODIFY, + }, + }, api2::types::{ + Authid, PROXMOX_CONFIG_DIGEST_SCHEMA, CHANGER_NAME_SCHEMA, SCSI_CHANGER_PATH_SCHEMA, @@ -42,6 +51,9 @@ use crate::{ }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "changer"], PRIV_TAPE_MODIFY, false), + }, )] /// Create a new changer device pub fn create_changer( @@ -94,7 +106,9 @@ pub fn create_changer( returns: { type: ScsiTapeChanger, }, - + access: { + permission: &Permission::Privilege(&["tape", "changer", "{name}"], PRIV_TAPE_AUDIT, false), + }, )] /// Get tape changer configuration pub fn get_config( @@ -123,17 +137,31 @@ pub fn get_config( type: ScsiTapeChanger, }, }, + access: { + description: "List configured tape changer filtered by Tape.Audit privileges", + permission: &Permission::Anybody, + }, )] /// List changers pub fn list_changers( _param: Value, mut rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; let (config, digest) = config::drive::config()?; let list: Vec = config.convert_to_typed_array("changer")?; + let list = list + .into_iter() + .filter(|changer| { + let privs = user_info.lookup_privs(&auth_id, &["tape", "changer", &changer.name]); + privs & PRIV_TAPE_AUDIT != 0 + }) + .collect(); + rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); Ok(list) @@ -177,6 +205,9 @@ pub enum DeletableProperty { }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "changer", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Update a tape changer configuration pub fn update_changer( @@ -251,6 +282,9 @@ pub fn update_changer( }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "changer", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Delete a tape changer configuration pub fn delete_changer(name: String, _param: Value) -> Result<(), Error> { diff --git a/src/api2/config/drive.rs b/src/api2/config/drive.rs index 3e0c7194..73d0eab4 100644 --- a/src/api2/config/drive.rs +++ b/src/api2/config/drive.rs @@ -2,11 +2,19 @@ use anyhow::{bail, Error}; use ::serde::{Deserialize, Serialize}; use serde_json::Value; -use proxmox::api::{api, Router, RpcEnvironment}; +use proxmox::api::{api, Router, RpcEnvironment, Permission}; use crate::{ - config, + config::{ + self, + cached_user_info::CachedUserInfo, + acl::{ + PRIV_TAPE_AUDIT, + PRIV_TAPE_MODIFY, + }, + }, api2::types::{ + Authid, PROXMOX_CONFIG_DIGEST_SCHEMA, DRIVE_NAME_SCHEMA, CHANGER_NAME_SCHEMA, @@ -41,6 +49,9 @@ use crate::{ }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "drive"], PRIV_TAPE_MODIFY, false), + }, )] /// Create a new drive pub fn create_drive(param: Value) -> Result<(), Error> { @@ -84,6 +95,9 @@ pub fn create_drive(param: Value) -> Result<(), Error> { returns: { type: LinuxTapeDrive, }, + access: { + permission: &Permission::Privilege(&["tape", "drive", "{name}"], PRIV_TAPE_AUDIT, false), + }, )] /// Get drive configuration pub fn get_config( @@ -112,17 +126,31 @@ pub fn get_config( type: LinuxTapeDrive, }, }, + access: { + description: "List configured tape drives filtered by Tape.Audit privileges", + permission: &Permission::Anybody, + }, )] /// List drives pub fn list_drives( _param: Value, mut rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; let (config, digest) = config::drive::config()?; let drive_list: Vec = config.convert_to_typed_array("linux")?; + let drive_list = drive_list + .into_iter() + .filter(|drive| { + let privs = user_info.lookup_privs(&auth_id, &["tape", "drive", &drive.name]); + privs & PRIV_TAPE_AUDIT != 0 + }) + .collect(); + rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); Ok(drive_list) @@ -173,6 +201,9 @@ pub enum DeletableProperty { }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "drive", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Update a drive configuration pub fn update_drive( @@ -246,6 +277,9 @@ pub fn update_drive( }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "drive", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Delete a drive configuration pub fn delete_drive(name: String, _param: Value) -> Result<(), Error> { diff --git a/src/api2/config/media_pool.rs b/src/api2/config/media_pool.rs index 613c6430..dc0222a6 100644 --- a/src/api2/config/media_pool.rs +++ b/src/api2/config/media_pool.rs @@ -6,11 +6,13 @@ use proxmox::{ api, Router, RpcEnvironment, + Permission, }, }; use crate::{ api2::types::{ + Authid, MEDIA_POOL_NAME_SCHEMA, MEDIA_SET_NAMING_TEMPLATE_SCHEMA, MEDIA_SET_ALLOCATION_POLICY_SCHEMA, @@ -19,7 +21,14 @@ use crate::{ SINGLE_LINE_COMMENT_SCHEMA, MediaPoolConfig, }, - config, + config::{ + self, + cached_user_info::CachedUserInfo, + acl::{ + PRIV_TAPE_AUDIT, + PRIV_TAPE_MODIFY, + }, + }, }; #[api( @@ -32,6 +41,9 @@ use crate::{ }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "pool"], PRIV_TAPE_MODIFY, false), + }, )] /// Create a new media pool pub fn create_pool( @@ -61,15 +73,29 @@ pub fn create_pool( type: MediaPoolConfig, }, }, + access: { + description: "List configured media pools filtered by Tape.Audit privileges", + permission: &Permission::Anybody, + }, )] /// List media pools pub fn list_pools( mut rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; let (config, digest) = config::media_pool::config()?; - let list = config.convert_to_typed_array("pool")?; + let list = config.convert_to_typed_array::("pool")?; + + let list = list + .into_iter() + .filter(|pool| { + let privs = user_info.lookup_privs(&auth_id, &["tape", "pool", &pool.name]); + privs & PRIV_TAPE_AUDIT != 0 + }) + .collect(); rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); @@ -87,6 +113,9 @@ pub fn list_pools( returns: { type: MediaPoolConfig, }, + access: { + permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_AUDIT, false), + }, )] /// Get media pool configuration pub fn get_config(name: String) -> Result { @@ -152,6 +181,9 @@ pub enum DeletableProperty { }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Update media pool settings pub fn update_pool( @@ -212,6 +244,9 @@ pub fn update_pool( }, }, }, + access: { + permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false), + }, )] /// Delete a media pool configuration pub fn delete_pool(name: String) -> Result<(), Error> { diff --git a/src/api2/tape/changer.rs b/src/api2/tape/changer.rs index f81341cc..be9e76c2 100644 --- a/src/api2/tape/changer.rs +++ b/src/api2/tape/changer.rs @@ -4,12 +4,19 @@ use std::path::Path; use anyhow::Error; use serde_json::Value; -use proxmox::api::{api, Router, SubdirMap}; +use proxmox::api::{api, Router, SubdirMap, RpcEnvironment, Permission}; use proxmox::list_subdirs_api_method; use crate::{ - config, + config::{ + self, + cached_user_info::CachedUserInfo, + acl::{ + PRIV_TAPE_AUDIT, + }, + }, api2::types::{ + Authid, CHANGER_NAME_SCHEMA, ChangerListEntry, LinuxTapeDrive, @@ -178,11 +185,18 @@ pub async fn transfer( type: ChangerListEntry, }, }, + access: { + description: "List configured tape changer filtered by Tape.Audit privileges", + permission: &Permission::Anybody, + }, )] /// List changers pub fn list_changers( _param: Value, + rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; let (config, _digest) = config::drive::config()?; @@ -193,6 +207,11 @@ pub fn list_changers( let mut list = Vec::new(); for changer in changer_list { + let privs = user_info.lookup_privs(&auth_id, &["tape", "changer", &changer.name]); + if (privs & PRIV_TAPE_AUDIT) == 0 { + continue; + } + let info = lookup_device_identification(&linux_changers, &changer.path); let entry = ChangerListEntry { config: changer, info }; list.push(entry); diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index f3cb1470..4d901e8b 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -16,6 +16,7 @@ use proxmox::{ section_config::SectionConfigData, RpcEnvironment, RpcEnvironmentType, + Permission, Router, SubdirMap, }, @@ -23,7 +24,13 @@ use proxmox::{ use crate::{ task_log, - config, + config::{ + self, + cached_user_info::CachedUserInfo, + acl::{ + PRIV_TAPE_AUDIT, + }, + }, api2::{ types::{ UPID_SCHEMA, @@ -1203,12 +1210,19 @@ pub fn catalog_media( type: DriveListEntry, }, }, + access: { + description: "List configured tape drives filtered by Tape.Audit privileges", + permission: &Permission::Anybody, + }, )] /// List drives pub fn list_drives( changer: Option, _param: Value, + rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; let (config, _) = config::drive::config()?; @@ -1223,6 +1237,11 @@ pub fn list_drives( continue; } + let privs = user_info.lookup_privs(&auth_id, &["tape", "drive", &drive.name]); + if (privs & PRIV_TAPE_AUDIT) == 0 { + continue; + } + let info = lookup_device_identification(&linux_drives, &drive.path); let state = get_tape_device_state(&config, &drive.name)?; let entry = DriveListEntry { config: drive, info, state };