diff --git a/src/http.rs b/src/http.rs index 991a9fa..ebf9809 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,4 +1,5 @@ use std::{ + io::ErrorKind, net::{IpAddr, Ipv4Addr, SocketAddr}, path::Path, sync::{atomic::Ordering, Arc, RwLock}, @@ -171,7 +172,16 @@ pub async fn run_setup( let setup_server = ProxySetupServer::new(logs_rx); let cert_dir = Path::new(&env_config.cert_dir); if !cert_dir.exists() { - tokio::fs::create_dir_all(cert_dir).await?; + tokio::fs::create_dir_all(cert_dir).await.map_err(|err| { + if err.kind() == ErrorKind::PermissionDenied { + anyhow::anyhow!( + "Cannot create certificate directory {}. Permission denied.", + cert_dir.display() + ) + } else { + err.into() + } + })?; } // Only attempt setup if not already configured @@ -197,8 +207,32 @@ pub async fn run_setup( let cert_path = cert_dir.join(GRPC_CERT_NAME); let key_path = cert_dir.join(GRPC_KEY_NAME); - tokio::fs::write(&cert_path, grpc_cert_pem).await?; - tokio::fs::write(&key_path, grpc_key_pem).await?; + tokio::fs::write(&cert_path, grpc_cert_pem) + .await + .map_err(|err| { + if err.kind() == ErrorKind::PermissionDenied { + anyhow::anyhow!( + "Cannot write certificate file {}. Permission denied for certificate directory {}.", + cert_path.display(), + cert_dir.display() + ) + } else { + err.into() + } + })?; + tokio::fs::write(&key_path, grpc_key_pem) + .await + .map_err(|err| { + if err.kind() == ErrorKind::PermissionDenied { + anyhow::anyhow!( + "Cannot write key file {}. Permission denied for certificate directory {}.", + key_path.display(), + cert_dir.display() + ) + } else { + err.into() + } + })?; Ok(configuration) } diff --git a/src/main.rs b/src/main.rs index 9106e2e..b2bae52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{fs::read_to_string, sync::Arc}; +use std::{fs::read_to_string, io::ErrorKind, path::Path, sync::Arc}; use defguard_proxy::{ config::get_env_config, @@ -10,6 +10,29 @@ use defguard_proxy::{ use defguard_version::Version; use tokio::sync::{mpsc, Mutex}; +fn read_optional_cert_file( + file_path: &Path, + cert_dir: &Path, + file_label: &'static str, +) -> anyhow::Result> { + match read_to_string(file_path) { + Ok(content) => Ok(Some(content)), + Err(err) if err.kind() == ErrorKind::NotFound => Ok(None), + Err(err) if err.kind() == ErrorKind::PermissionDenied => anyhow::bail!( + "Cannot access {file_label} file {}. Permission denied for certificate directory {}.", + file_path.display(), + cert_dir.display() + ), + Err(err) => { + tracing::warn!( + "Failed to read gRPC {file_label} at {}: {err}", + file_path.display() + ); + Ok(None) + } + } +} + #[tokio::main] async fn main() -> anyhow::Result<()> { // configuration @@ -19,10 +42,11 @@ async fn main() -> anyhow::Result<()> { let env_config = get_env_config()?; let cert_dir = env_config.cert_dir.clone(); - let (grpc_cert, grpc_key) = ( - read_to_string(cert_dir.join(GRPC_CERT_NAME)).ok(), - read_to_string(cert_dir.join(GRPC_KEY_NAME)).ok(), - ); + let grpc_cert_path = cert_dir.join(GRPC_CERT_NAME); + let grpc_key_path = cert_dir.join(GRPC_KEY_NAME); + + let grpc_cert = read_optional_cert_file(&grpc_cert_path, &cert_dir, "certificate")?; + let grpc_key = read_optional_cert_file(&grpc_key_path, &cert_dir, "key")?; let proxy_configuration = if let (Some(grpc_cert), Some(grpc_key)) = (grpc_cert, grpc_key) { Some(Configuration {