use std::{
fs::{Permissions, create_dir_all, set_permissions},
os::unix::fs::{PermissionsExt, chown},
path::PathBuf,
};
use crate::common::{CREDENTIALS_DIR_MODE, get_data_home};
const PLAINTEXT_CREDENTIALS_FILE: &str = "admin-credentials.toml";
const SYSTEMD_CREDS_CREDENTIALS_FILE: &str = "admin-credentials.creds";
const CREDENTIALS_DIR: &str = "creds/";
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unable to apply permissions {permissions} to {path}:\n{source}")]
ApplyPermissions {
permissions: u32,
path: PathBuf,
source: std::io::Error,
},
#[error("Unable to create directory {dir}:\n{source}")]
CreateDirectory {
dir: &'static str,
source: std::io::Error,
},
#[error("Ownership of directory {dir} can not be changed to user {system_user}: {source}")]
DirChangeOwner {
dir: PathBuf,
system_user: String,
source: std::io::Error,
},
}
pub fn get_credentials_dir() -> PathBuf {
get_data_home().join(PathBuf::from(CREDENTIALS_DIR))
}
pub fn get_plaintext_credentials_file() -> PathBuf {
get_credentials_dir().join(PathBuf::from(PLAINTEXT_CREDENTIALS_FILE))
}
pub fn get_systemd_creds_credentials_file() -> PathBuf {
get_credentials_dir().join(PathBuf::from(SYSTEMD_CREDS_CREDENTIALS_FILE))
}
pub fn create_credentials_dir() -> Result<(), Error> {
let credentials_dir = get_credentials_dir();
create_dir_all(credentials_dir.as_path()).map_err(|source| Error::CreateDirectory {
dir: CREDENTIALS_DIR,
source,
})?;
set_permissions(
credentials_dir.as_path(),
Permissions::from_mode(CREDENTIALS_DIR_MODE),
)
.map_err(|source| Error::ApplyPermissions {
permissions: CREDENTIALS_DIR_MODE,
path: credentials_dir.clone(),
source,
})?;
let data_home = get_data_home();
let mut chown_dir = credentials_dir.clone();
while chown_dir != data_home {
chown(&chown_dir, Some(0), Some(0)).map_err(|source| Error::DirChangeOwner {
dir: chown_dir.to_path_buf(),
system_user: "root".to_string(),
source,
})?;
if let Some(parent) = &chown_dir.parent() {
chown_dir = parent.to_path_buf()
} else {
break;
}
}
Ok(())
}