forked from proxmox-mirrors/proxmox
product-config: factor out methods to create different file creation options
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
parent
7cd240bbad
commit
237f6218b0
@ -7,14 +7,73 @@ use nix::fcntl::OFlag;
|
||||
use nix::sys::stat::Mode;
|
||||
use nix::unistd::{Gid, Uid};
|
||||
|
||||
use proxmox_sys::fs::CreateOptions;
|
||||
|
||||
use super::product_config;
|
||||
|
||||
// Check file/directory permissions
|
||||
//
|
||||
// For security reasons, we want to make sure they are set correctly:
|
||||
// * owned by uid/gid
|
||||
// * nobody else can read (mode 0700)
|
||||
pub fn check_permissions<P: AsRef<Path>>(dir: P, uid: Uid, gid: Gid, mode: u32) -> Result<(), Error> {
|
||||
/// Return [CreateOptions] for files owned by `api_user.uid/api_user.gid` with mode `0640`.
|
||||
pub fn default_create_options() -> CreateOptions {
|
||||
let api_user = &product_config().api_user;
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
|
||||
proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(api_user.uid)
|
||||
.group(api_user.gid)
|
||||
}
|
||||
|
||||
/// Return [CreateOptions] for files owned by `root:api-user.gid` with permission `0640`.
|
||||
///
|
||||
/// Only the superuser can write those files, but group `api-user.gid` can read them.
|
||||
pub fn privileged_create_options() -> CreateOptions {
|
||||
let api_user = &product_config().api_user;
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
|
||||
proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(api_user.gid)
|
||||
}
|
||||
|
||||
/// Return [CreateOptions] for files owned by `root:root` with permission `0600`.
|
||||
///
|
||||
/// Only the superuser can read and write those files.
|
||||
pub fn secret_create_options() -> CreateOptions {
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0600);
|
||||
proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(nix::unistd::Gid::from_raw(0))
|
||||
}
|
||||
|
||||
/// Return [CreateOptions] for files owned by `root:root` with permission `0644`.
|
||||
///
|
||||
/// Everyone can read, but only the superuser can write those files. This is usually used
|
||||
/// for system configuration files inside "/etc/" (i.e. "/etc/resolv.conf").
|
||||
pub fn system_config_create_options() -> CreateOptions {
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0644);
|
||||
proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(nix::unistd::Gid::from_raw(0))
|
||||
}
|
||||
|
||||
/// Return [CreateOptions] for lock files, owner `api_user.uid/api_user.gid` and mode `0660`.
|
||||
pub fn lockfile_create_options() -> CreateOptions {
|
||||
let api_user = &product_config().api_user;
|
||||
proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(nix::sys::stat::Mode::from_bits_truncate(0o660))
|
||||
.owner(api_user.uid)
|
||||
.group(api_user.gid)
|
||||
}
|
||||
|
||||
/// Check file/directory permissions.
|
||||
///
|
||||
/// Make sure that the file or dir is owned by uid/gid and has the correct mode.
|
||||
pub fn check_permissions<P: AsRef<Path>>(
|
||||
dir: P,
|
||||
uid: Uid,
|
||||
gid: Gid,
|
||||
mode: u32,
|
||||
) -> Result<(), Error> {
|
||||
let uid = uid.as_raw();
|
||||
let gid = gid.as_raw();
|
||||
let dir = dir.as_ref();
|
||||
@ -43,7 +102,12 @@ pub fn check_permissions<P: AsRef<Path>>(dir: P, uid: Uid, gid: Gid, mode: u32)
|
||||
/// Create a new directory with uid/gid and mode.
|
||||
///
|
||||
/// Returns Ok if the directory already exists with correct access permissions.
|
||||
pub fn mkdir_permissions<P: AsRef<Path>>(dir: P, uid: Uid, gid: Gid, mode: u32) -> Result<(), Error> {
|
||||
pub fn mkdir_permissions<P: AsRef<Path>>(
|
||||
dir: P,
|
||||
uid: Uid,
|
||||
gid: Gid,
|
||||
mode: u32,
|
||||
) -> Result<(), Error> {
|
||||
let nix_mode = Mode::from_bits(mode).expect("bad mode bits for nix crate");
|
||||
let dir = dir.as_ref();
|
||||
|
||||
@ -69,78 +133,47 @@ pub fn mkdir_permissions<P: AsRef<Path>>(dir: P, uid: Uid, gid: Gid, mode: u32)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Atomically write data to file owned by `root:api-user` with permission `0640`
|
||||
/// Atomically write data to file owned by `root:api-user.gid` with permission `0640`
|
||||
///
|
||||
/// Only the superuser can write those files, but group 'api-user' can read them.
|
||||
pub fn replace_privileged_config<P: AsRef<std::path::Path>>(
|
||||
path: P,
|
||||
data: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
let api_user = &product_config().api_user;
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
|
||||
// set the correct owner/group/permissions while saving file
|
||||
// owner(rw) = root, group(r)= api-user
|
||||
let options = proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(api_user.gid);
|
||||
|
||||
let options = privileged_create_options();
|
||||
proxmox_sys::fs::replace_file(path, data, options, true)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Atomically write data to file owned by `api-user:api-user` with permission `0660`.
|
||||
/// Atomically write data to file owned by `api-user.uid:api-user.gid` with permission `0660`.
|
||||
pub fn replace_config<P: AsRef<std::path::Path>>(path: P, data: &[u8]) -> Result<(), Error> {
|
||||
let api_user = &product_config().api_user;
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
|
||||
// set the correct owner/group/permissions while saving file
|
||||
// owner(rw) = root, group(r)= api-user
|
||||
let options = proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(api_user.uid)
|
||||
.group(api_user.gid);
|
||||
|
||||
let options = default_create_options();
|
||||
proxmox_sys::fs::replace_file(path, data, options, true)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Atomically write data to file owned by "root:root" with permission "0600"
|
||||
/// Atomically write data to file owned by `root:root` with permission `0600`.
|
||||
///
|
||||
/// Only the superuser can read and write those files.
|
||||
pub fn replace_secret_config<P: AsRef<std::path::Path>>(path: P, data: &[u8]) -> Result<(), Error> {
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0600);
|
||||
// set the correct owner/group/permissions while saving file
|
||||
// owner(rw) = root, group(r)= root
|
||||
let options = proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(nix::unistd::Gid::from_raw(0));
|
||||
|
||||
let options = secret_create_options();
|
||||
proxmox_sys::fs::replace_file(path, data, options, true)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Atomically write data to file owned by "root:root" with permission "0644"
|
||||
/// Atomically write data to file owned by `root:root` with permission `0644`.
|
||||
///
|
||||
/// Everyone can read, but only the superuser can write those files. This is usually used
|
||||
/// for system configuration files inside "/etc/" (i.e. "/etc/resolv.conf").
|
||||
pub fn replace_system_config<P: AsRef<std::path::Path>>(path: P, data: &[u8]) -> Result<(), Error> {
|
||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0644);
|
||||
// set the correct owner/group/permissions while saving file
|
||||
// owner(rw) = root, group(r)= root
|
||||
let options = proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(mode)
|
||||
.owner(nix::unistd::ROOT)
|
||||
.group(nix::unistd::Gid::from_raw(0));
|
||||
|
||||
let options = system_config_create_options();
|
||||
proxmox_sys::fs::replace_file(path, data, options, true)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lock guard used by [open_api_lockfile]
|
||||
///
|
||||
/// The lock is released if you drop this guard.
|
||||
#[allow(dead_code)]
|
||||
pub struct ApiLockGuard(Option<std::fs::File>);
|
||||
|
||||
@ -150,26 +183,22 @@ pub unsafe fn create_mocked_lock() -> ApiLockGuard {
|
||||
ApiLockGuard(None)
|
||||
}
|
||||
|
||||
/// Open or create a lock file owned by user "api-user" and lock it.
|
||||
/// Open or create a lock file owned by user `api-user` and lock it.
|
||||
///
|
||||
/// Owner/Group of the file is set to api-user/api-group.
|
||||
/// File mode is 0660.
|
||||
/// Owner/Group of the file is set to `api-user.uid/api-user.gid`.
|
||||
/// File mode is `0660`.
|
||||
/// Default timeout is 10 seconds.
|
||||
///
|
||||
/// Note: This method needs to be called by user "root" or "api-user".
|
||||
/// The lock is released as soon as you drop the returned lock guard.
|
||||
///
|
||||
/// Note: This method needs to be called by user `root` or `api-user`.
|
||||
pub fn open_api_lockfile<P: AsRef<std::path::Path>>(
|
||||
path: P,
|
||||
timeout: Option<std::time::Duration>,
|
||||
exclusive: bool,
|
||||
) -> Result<ApiLockGuard, Error> {
|
||||
let api_user = &product_config().api_user;
|
||||
let options = proxmox_sys::fs::CreateOptions::new()
|
||||
.perm(nix::sys::stat::Mode::from_bits_truncate(0o660))
|
||||
.owner(api_user.uid)
|
||||
.group(api_user.gid);
|
||||
|
||||
let options = lockfile_create_options();
|
||||
let timeout = timeout.unwrap_or(std::time::Duration::new(10, 0));
|
||||
|
||||
let file = proxmox_sys::fs::open_file_locked(&path, timeout, exclusive, options)?;
|
||||
Ok(ApiLockGuard(Some(file)))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user