chore: remove SESSION_SECRET and wrap master_encryption_key in Arc

SESSION_SECRET was loaded and validated but never used anywhere in the
codebase. master_encryption_key is now wrapped in Arc<String> to avoid
cloning the secret string on every AppState clone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
master
oabrivard 3 months ago
parent 150090a112
commit 69c1688bc7

@ -15,10 +15,6 @@ POSTGRES_PASSWORD=CHANGE_ME
# Generate with: openssl rand -hex 32 # Generate with: openssl rand -hex 32
MASTER_ENCRYPTION_KEY= MASTER_ENCRYPTION_KEY=
# Secret for signing session cookies (at least 64 characters).
# Generate with: openssl rand -hex 32
SESSION_SECRET=
# --- Application --- # --- Application ---
# Public URL where the app is accessible (no trailing slash). # Public URL where the app is accessible (no trailing slash).
# Used for magic link URLs, CORS origin, and cookie domain. # Used for magic link URLs, CORS origin, and cookie domain.

@ -4,6 +4,7 @@
//! to start with invalid configuration rather than failing at runtime. //! to start with invalid configuration rather than failing at runtime.
use std::env; use std::env;
use std::sync::Arc;
/// Typed application configuration. /// Typed application configuration.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -12,8 +13,7 @@ pub struct AppConfig {
pub database_url: String, pub database_url: String,
// Security // Security
pub session_secret: String, pub master_encryption_key: Arc<String>,
pub master_encryption_key: String,
// Application // Application
pub app_url: String, pub app_url: String,
@ -36,7 +36,6 @@ impl AppConfig {
/// Fails fast with a clear error message if a required variable is missing. /// Fails fast with a clear error message if a required variable is missing.
pub fn from_env() -> Result<Self, String> { pub fn from_env() -> Result<Self, String> {
let database_url = required_var("DATABASE_URL")?; let database_url = required_var("DATABASE_URL")?;
let session_secret = required_var("SESSION_SECRET")?;
let master_encryption_key = required_var("MASTER_ENCRYPTION_KEY")?; let master_encryption_key = required_var("MASTER_ENCRYPTION_KEY")?;
let app_url = required_var("APP_URL")?; let app_url = required_var("APP_URL")?;
let resend_api_key = required_var("RESEND_API_KEY")?; let resend_api_key = required_var("RESEND_API_KEY")?;
@ -54,8 +53,7 @@ impl AppConfig {
Ok(Self { Ok(Self {
database_url, database_url,
session_secret, master_encryption_key: Arc::new(master_encryption_key),
master_encryption_key,
app_url, app_url,
port, port,
static_dir, static_dir,
@ -79,10 +77,6 @@ impl AppConfig {
); );
} }
if self.session_secret.len() < 64 {
return Err("SESSION_SECRET must be at least 64 characters".into());
}
if !self.app_url.starts_with("http://") && !self.app_url.starts_with("https://") { if !self.app_url.starts_with("http://") && !self.app_url.starts_with("https://") {
return Err("APP_URL must start with http:// or https://".into()); return Err("APP_URL must start with http:// or https://".into());
} }
@ -113,8 +107,7 @@ mod tests {
fn test_validate_valid_config() { fn test_validate_valid_config() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("ab".repeat(32)),
master_encryption_key: "ab".repeat(32),
app_url: "https://synth.example.com".into(), app_url: "https://synth.example.com".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),
@ -130,8 +123,7 @@ mod tests {
fn test_validate_bad_encryption_key_length() { fn test_validate_bad_encryption_key_length() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("abcd".into()), // too short
master_encryption_key: "abcd".into(), // too short
app_url: "https://synth.example.com".into(), app_url: "https://synth.example.com".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),
@ -148,8 +140,7 @@ mod tests {
fn test_validate_bad_encryption_key_not_hex() { fn test_validate_bad_encryption_key_not_hex() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("zz".repeat(32)), // not hex
master_encryption_key: "zz".repeat(32), // not hex
app_url: "https://synth.example.com".into(), app_url: "https://synth.example.com".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),
@ -162,30 +153,11 @@ mod tests {
assert!(err.contains("MASTER_ENCRYPTION_KEY")); assert!(err.contains("MASTER_ENCRYPTION_KEY"));
} }
#[test]
fn test_validate_short_session_secret() {
let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "short".into(),
master_encryption_key: "ab".repeat(32),
app_url: "https://synth.example.com".into(),
port: 8080,
static_dir: "./static".into(),
resend_api_key: "re_test".into(),
email_from: "test@example.com".into(),
turnstile_secret_key: "0x4AAA".into(),
turnstile_site_key: "0x4BBB".into(),
};
let err = config.validate().unwrap_err();
assert!(err.contains("SESSION_SECRET"));
}
#[test] #[test]
fn test_validate_bad_app_url_scheme() { fn test_validate_bad_app_url_scheme() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("ab".repeat(32)),
master_encryption_key: "ab".repeat(32),
app_url: "ftp://synth.example.com".into(), app_url: "ftp://synth.example.com".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),
@ -202,8 +174,7 @@ mod tests {
fn test_validate_trailing_slash() { fn test_validate_trailing_slash() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("ab".repeat(32)),
master_encryption_key: "ab".repeat(32),
app_url: "https://synth.example.com/".into(), app_url: "https://synth.example.com/".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),
@ -220,8 +191,7 @@ mod tests {
fn test_is_secure() { fn test_is_secure() {
let config = AppConfig { let config = AppConfig {
database_url: "postgres://user:pass@localhost/db".into(), database_url: "postgres://user:pass@localhost/db".into(),
session_secret: "a".repeat(64), master_encryption_key: Arc::new("ab".repeat(32)),
master_encryption_key: "ab".repeat(32),
app_url: "https://synth.example.com".into(), app_url: "https://synth.example.com".into(),
port: 8080, port: 8080,
static_dir: "./static".into(), static_dir: "./static".into(),

Loading…
Cancel
Save