Files
proxmox-backup/src/api2/reader/environment.rs
Fabian Grünbichler d479f0c810 reader: track index chunks and limit access
a reader connection should not be allowed to read arbitrary chunks in
the datastore, but only those that were previously registered by opening
the corresponding index files.

this mechanism is needed to allow unprivileged users (that don't have
full READ permissions on the whole datastore) access to their own
backups via a reader environment.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
2020-10-09 12:54:09 +02:00

105 lines
2.5 KiB
Rust

use std::sync::{Arc,RwLock};
use std::collections::HashSet;
use serde_json::{json, Value};
use proxmox::api::{RpcEnvironment, RpcEnvironmentType};
use crate::api2::types::Userid;
use crate::backup::*;
use crate::server::formatter::*;
use crate::server::WorkerTask;
//use proxmox::tools;
/// `RpcEnvironmet` implementation for backup reader service
#[derive(Clone)]
pub struct ReaderEnvironment {
env_type: RpcEnvironmentType,
result_attributes: Value,
user: Userid,
pub debug: bool,
pub formatter: &'static OutputFormatter,
pub worker: Arc<WorkerTask>,
pub datastore: Arc<DataStore>,
pub backup_dir: BackupDir,
allowed_chunks: Arc<RwLock<HashSet<[u8;32]>>>,
}
impl ReaderEnvironment {
pub fn new(
env_type: RpcEnvironmentType,
user: Userid,
worker: Arc<WorkerTask>,
datastore: Arc<DataStore>,
backup_dir: BackupDir,
) -> Self {
Self {
result_attributes: json!({}),
env_type,
user,
worker,
datastore,
debug: false,
formatter: &JSON_FORMATTER,
backup_dir,
allowed_chunks: Arc::new(RwLock::new(HashSet::new())),
}
}
pub fn log<S: AsRef<str>>(&self, msg: S) {
self.worker.log(msg);
}
pub fn debug<S: AsRef<str>>(&self, msg: S) {
if self.debug { self.worker.log(msg); }
}
pub fn register_chunk(&self, digest: [u8;32]) {
let mut allowed_chunks = self.allowed_chunks.write().unwrap();
allowed_chunks.insert(digest);
}
pub fn check_chunk_access(&self, digest: [u8;32]) -> bool {
self.allowed_chunks.read().unwrap().contains(&digest)
}
}
impl RpcEnvironment for ReaderEnvironment {
fn result_attrib_mut(&mut self) -> &mut Value {
&mut self.result_attributes
}
fn result_attrib(&self) -> &Value {
&self.result_attributes
}
fn env_type(&self) -> RpcEnvironmentType {
self.env_type
}
fn set_user(&mut self, _user: Option<String>) {
panic!("unable to change user");
}
fn get_user(&self) -> Option<String> {
Some(self.user.to_string())
}
}
impl AsRef<ReaderEnvironment> for dyn RpcEnvironment {
fn as_ref(&self) -> &ReaderEnvironment {
self.as_any().downcast_ref::<ReaderEnvironment>().unwrap()
}
}
impl AsRef<ReaderEnvironment> for Box<dyn RpcEnvironment> {
fn as_ref(&self) -> &ReaderEnvironment {
self.as_any().downcast_ref::<ReaderEnvironment>().unwrap()
}
}