diff --git a/server/src/main.rs b/server/src/main.rs index 652f018c6..464b39307 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -64,6 +64,7 @@ async fn main() -> anyhow::Result<()> { env_logger::init(); CONFIG.validate(); let storage = CONFIG.storage().get_object_store(); + CONFIG.validate_staging()?; CONFIG.validate_storage(&*storage).await; let metadata = storage::resolve_parseable_metadata().await?; banner::print(&CONFIG, metadata); diff --git a/server/src/option.rs b/server/src/option.rs index 3f4b4e2a0..0025517b8 100644 --- a/server/src/option.rs +++ b/server/src/option.rs @@ -26,6 +26,7 @@ use crate::storage::{ FSConfig, ObjectStorage, ObjectStorageError, ObjectStorageProvider, S3Config, LOCAL_SYNC_INTERVAL, }; +use crate::utils::validate_path_is_writeable; lazy_static::lazy_static! { #[derive(Debug)] @@ -112,6 +113,11 @@ impl Config { } } + pub fn validate_staging(&self) -> anyhow::Result<()> { + let staging_path = self.staging_dir(); + validate_path_is_writeable(staging_path) + } + pub fn storage(&self) -> Arc { self.storage.clone() } diff --git a/server/src/storage/localfs.rs b/server/src/storage/localfs.rs index 20daa2c18..277db8601 100644 --- a/server/src/storage/localfs.rs +++ b/server/src/storage/localfs.rs @@ -36,7 +36,7 @@ use relative_path::RelativePath; use tokio::fs; use tokio_stream::wrappers::ReadDirStream; -use crate::{option::validation, query::Query}; +use crate::{option::validation, query::Query, utils::validate_path_is_writeable}; use super::{LogStream, ObjectStorage, ObjectStorageError, ObjectStorageProvider}; @@ -117,7 +117,9 @@ impl ObjectStorage for LocalFS { } async fn check(&self) -> Result<(), ObjectStorageError> { - Ok(fs::create_dir_all(&self.root).await?) + fs::create_dir_all(&self.root).await?; + validate_path_is_writeable(&self.root) + .map_err(|e| ObjectStorageError::UnhandledError(e.into())) } async fn delete_stream(&self, stream_name: &str) -> Result<(), ObjectStorageError> { diff --git a/server/src/utils.rs b/server/src/utils.rs index 3636a8b09..bc5fe2fa7 100644 --- a/server/src/utils.rs +++ b/server/src/utils.rs @@ -16,6 +16,8 @@ * */ +use std::path::Path; + use chrono::{DateTime, NaiveDate, Timelike, Utc}; use serde_json::{json, Value}; @@ -122,6 +124,15 @@ pub fn capitalize_ascii(s: &str) -> String { s[0..1].to_uppercase() + &s[1..] } +pub fn validate_path_is_writeable(path: &Path) -> anyhow::Result<()> { + let Ok(md) = std::fs::metadata(path) else { anyhow::bail!("Could not read metadata for staging dir") }; + let permissions = md.permissions(); + if permissions.readonly() { + anyhow::bail!("Staging directory {} is unwritable", path.display()) + } + Ok(()) +} + pub mod uid { use ulid::Ulid;