From 5ec01e591e08833e59381dab7bb610959eb114d7 Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Wed, 29 Apr 2026 04:23:58 +0300 Subject: [PATCH] refactor: Replace fallback defaults with required environment variable validation in charging-engine auth - Change AuthConfig::from_env() return type from Self to Result - Remove default JWT_SECRET fallback, require environment variable to be set - Add validation requiring JWT_SECRET to be at least 32 characters for security - Replace expect() with ok_or_else in create_token timestamp calculation - Replace expect() with map_err in DATABASE_URL environment variable loading --- apps/charging-engine/src/auth.rs | 13 +++++++++---- apps/charging-engine/src/main.rs | 5 +++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/charging-engine/src/auth.rs b/apps/charging-engine/src/auth.rs index fb4a761..e597a8d 100644 --- a/apps/charging-engine/src/auth.rs +++ b/apps/charging-engine/src/auth.rs @@ -21,8 +21,13 @@ pub struct AuthConfig { } impl AuthConfig { - pub fn from_env() -> Self { - let secret = env::var("JWT_SECRET").unwrap_or_else(|_| "default_secret_key_change_in_production".to_string()); + pub fn from_env() -> Result { + let secret = env::var("JWT_SECRET") + .map_err(|_| "JWT_SECRET environment variable is required".to_string())?; + + if secret.len() < 32 { + return Err("JWT_SECRET must be at least 32 characters for security".to_string()); + } // Parse API keys from comma-separated environment variable let api_keys_env = env::var("API_KEYS").unwrap_or_else(|_| String::new()); @@ -32,7 +37,7 @@ impl AuthConfig { .filter(|s| !s.is_empty()) .collect(); - Self { secret, api_keys } + Ok(Self { secret, api_keys }) } pub fn validate_api_key(&self, api_key: &str) -> bool { @@ -43,7 +48,7 @@ impl AuthConfig { pub fn create_token(user_id: &str, config: &AuthConfig) -> Result { let expiration = chrono::Utc::now() .checked_add_signed(chrono::Duration::hours(24)) - .expect("valid timestamp") + .ok_or_else(|| StatusCode::INTERNAL_SERVER_ERROR)? .timestamp() as usize; let claims = Claims { diff --git a/apps/charging-engine/src/main.rs b/apps/charging-engine/src/main.rs index e882a4f..b90c6ef 100644 --- a/apps/charging-engine/src/main.rs +++ b/apps/charging-engine/src/main.rs @@ -29,7 +29,7 @@ async fn main() -> Result<()> { // Initialize charging engine let redis_url = std::env::var("REDIS_URI").unwrap_or_else(|_| "redis://127.0.0.1/".to_string()); let database_url = std::env::var("DATABASE_URL") - .expect("DATABASE_URL is required (for rating plans)"); + .map_err(|_| anyhow::anyhow!("DATABASE_URL environment variable is required (for rating plans)"))?; let sync_interval = std::env::var("SYNC_INTERVAL") .unwrap_or_else(|_| "1".to_string()) .parse::() @@ -47,7 +47,8 @@ async fn main() -> Result<()> { info!("Connected to Redis successfully"); // Create application state - let auth_config = AuthConfig::from_env(); + let auth_config = AuthConfig::from_env() + .map_err(|e| anyhow::anyhow!("Failed to initialize auth config: {}", e))?; let state = crate::models::AppState { charging_engine, auth_config,