This guide provides comprehensive security best practices and guidelines for developers working on the Fortress security platform. It covers secure coding practices, authentication patterns, input validation, and security testing.
- Security Architecture
- Authentication & Authorization
- Input Validation & Sanitization
- Session Management
- Cryptographic Security
- Error Handling
- Security Testing
- Common Security Pitfalls
- Performance Considerations
- Security Monitoring
Fortress implements a layered security architecture:
Application Layer
- Input Validation & Sanitization
- CSRF Protection
- Security Headers
Authentication Layer
- API Key Authentication
- Session Token Validation
- Rate Limiting & Lockout
Cryptographic Layer
- Secure Random Number Generation
- Encryption & Decryption
- Key Management
security_fixes: Core security utilities and enhancementswebsocket::auth: WebSocket authentication and authorizationtrng: True Random Number Generatorencryption: Cryptographic operationsauth: Core authentication system
use crate::websocket::auth::AuthManager;
// Secure API key authentication
let auth_manager = AuthManager::new();
let result = auth_manager.authenticate_api_key(api_key, client_ip).await?;
if result.success {
// Authentication successful
let user_id = result.user_id.unwrap();
let roles = result.roles;
} else {
// Authentication failed
log_security_event("api_key_auth_failed", client_ip);
}// Secure session token validation
let result = auth_manager.authenticate_session(session_token, client_ip).await?;
if result.success {
let session_data = result.session_id.unwrap();
// Process authenticated request
} else {
// Return authentication error
}Rate limiting is automatically enforced by the AuthManager:
let auth_config = AuthConfig {
max_attempts_per_ip: 10,
attempt_window_seconds: 300,
lockout_duration_seconds: 900,
};
let auth_manager = AuthManager::new_with_config(auth_config);use crate::security_fixes::InputValidator;
// Email validation
let email = InputValidator::validate_email(user_input)?;
if email.is_ok() {
// Email is valid and safe
}
// URL validation
let url = InputValidator::validate_url(user_input)?;
// Filename validation
let filename = InputValidator::validate_filename(user_input)?;fn validate_custom_input(input: &str) -> Result<String> {
// Length validation
if input.is_empty() || input.len() > 100 {
return Err(FortressError::validation("Invalid input length", None, None));
}
// Character validation
if !input.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') {
return Err(FortressError::validation("Invalid characters", None, None));
}
// Dangerous pattern detection
let dangerous_patterns = ["<script", "javascript:", "data:"];
let input_lower = input.to_lowercase();
for pattern in &dangerous_patterns {
if input_lower.contains(pattern) {
return Err(FortressError::validation("Dangerous pattern detected", None, None));
}
}
Ok(input.to_string())
}use crate::security_fixes::SecureSessionGenerator;
let mut session_generator = SecureSessionGenerator::new();
let session_id = session_generator.generate_session_id()?;
// Session ID format: "session_<64_char_hex>"
assert!(session_id.starts_with("session_"));
assert!(session_id.len() > 40);use crate::security_fixes::CsrfProtection;
let mut csrf_protection = CsrfProtection::new();
// Generate CSRF token for session
let session_id = "user_session_123";
let csrf_token = csrf_protection.generate_token(session_id)?;
// Validate CSRF token
if csrf_protection.validate_token(session_id, &csrf_token) {
// Token is valid, proceed with request
} else {
return Err(FortressError::authentication("Invalid CSRF token"));
}
// Clean up token when session ends
csrf_protection.remove_token(session_id);use crate::security_fixes::SecurityHeaders;
let headers = SecurityHeaders::default();
let header_map = headers.as_map();
// Apply headers to HTTP response
for (name, value) in header_map {
response.headers_mut().insert(name, value.parse()?);
}use crate::trng;
// Generate cryptographically secure random bytes
let random_bytes = trng::random_bytes(32)?;
// Use for session tokens, nonces, etc.
let nonce = trng::random_bytes(12)?;use crate::encryption::Aegis256;
let algorithm = Aegis256::new();
let key = SecureKey::new(32)?; // 256-bit key
// Encrypt data
let plaintext = b"Sensitive data";
let ciphertext = algorithm.encrypt(plaintext, &key)?;
// Decrypt data
let decrypted = algorithm.decrypt(&ciphertext, &key)?;
assert_eq!(plaintext, decrypted);use crate::key::KeyManager;
let key_manager = KeyManager::new();
// Generate new key
let key = key_manager.generate_key(32)?;
// Store key securely
let key_id = key_manager.store_key(key.clone()).await?;
// Retrieve key
let retrieved_key = key_manager.get_key(&key_id).await?;
// Rotate key
let new_key = key_manager.rotate_key(&key_id).await?;use crate::error::FortressError;
// Authentication errors
return Err(FortressError::authentication("Invalid credentials"));
// Validation errors
return Err(FortressError::validation("Invalid input", None, None));
// Encryption errors
return Err(FortressError::encryption(
"Encryption failed",
"Aegis256",
EncryptionErrorCode::EncryptionFailed
));
// Authorization errors
return Err(FortressError::authorization("Access denied"));// NEVER use unwrap() in production code
// BAD:
let user_id = result.unwrap();
// GOOD:
let user_id = result.map_err(|e| {
log_security_event("operation_failed", &e.to_string());
FortressError::authentication("User lookup failed")
})?;
// Use ? operator for proper error propagation
let session_data = validate_session_token(session_token).await?;use crate::utils::constant_time_eq;
// Use constant-time comparison for sensitive data
if constant_time_eq(provided_hash, stored_hash) {
// Authentication successful
} else {
// Authentication failed (no timing difference)
}use crate::security_integration_tests::SecurityIntegrationTests;
#[tokio::test]
async fn test_security_integration() {
SecurityIntegrationTests::run_all_tests().await.unwrap();
}use crate::security_regression_tests::SecurityRegressionTests;
#[test]
fn test_security_regression() {
SecurityRegressionTests::run_all_tests().unwrap();
}use crate::security_performance_tests::SecurityPerformanceTests;
#[tokio::test]
async fn test_security_performance() {
SecurityPerformanceTests::run_all_tests().await.unwrap();
}#[cfg(test)]
mod security_tests {
use super::*;
#[test]
fn test_input_validation() {
assert!(InputValidator::validate_email("test@example.com").is_ok());
assert!(InputValidator::validate_email("invalid-email").is_err());
assert!(InputValidator::validate_url("https://example.com").is_ok());
assert!(InputValidator::validate_url("javascript:alert('xss')").is_err());
}
#[test]
fn test_csrf_protection() {
let mut csrf = CsrfProtection::new();
let session_id = "test_session";
let token = csrf.generate_token(session_id).unwrap();
assert!(csrf.validate_token(session_id, &token));
assert!(!csrf.validate_token(session_id, "invalid_token"));
}
}NEVER use placeholder authentication patterns:
// BAD - Vulnerable
let user_id = format!("user_{}", &api_key[..8]);
// GOOD - Secure
let api_key_hash = hash_api_key(api_key)?;
if !is_valid_api_key(&api_key_hash).await? {
return Err(FortressError::authentication("Invalid API key"));
}
let user_id = get_user_by_api_key(&api_key_hash).await?;NEVER use weak random number generators:
// BAD - Predictable
let mut rng = rand::thread_rng();
let random_bytes: Vec<u8> = (0..32).map(|_| rng.gen()).collect();
// GOOD - Cryptographically secure
let random_bytes = crate::trng::random_bytes(32)?;NEVER hardcode credentials:
// BAD - Security risk
auth.create_user("admin".to_string(), "password".to_string()).await.unwrap();
// GOOD - Secure credentials
let secure_password = crate::utils::generate_password(16);
auth.create_user("admin".to_string(), secure_password).await.unwrap();NEVER use unsafe string operations for sensitive data:
// BAD - Potential timing attack
if provided_password == stored_password {
// Authentication successful
}
// GOOD - Constant-time comparison
if constant_time_eq(provided_password.as_bytes(), stored_password.as_bytes()) {
// Authentication successful
}NEVER disclose sensitive information in error messages:
// BAD - Information disclosure
return Err(FortressError::authentication(format!("User {} not found", username)));
// GOOD - Generic error message
return Err(FortressError::authentication("Invalid credentials"));Security features should not significantly impact performance:
// Efficient session generation
let session_id = session_generator.generate_session_id()?; // < 5ms
// Fast input validation
let email = InputValidator::validate_email(input)?; // < 1ms
// Efficient rate limiting lookup
let result = auth_manager.authenticate_api_key(key, ip).await?; // < 10msCache frequently accessed security data:
// Cache user permissions
let cached_permissions = get_cached_permissions(&user_id);
if cached_permissions.is_none() {
let permissions = fetch_permissions_from_db(&user_id).await?;
cache_permissions(&user_id, &permissions);
}Process security operations in batches:
// Batch session validation
let session_ids = vec!["session1", "session2", "session3"];
let valid_sessions = validate_sessions_batch(session_ids).await?;fn log_security_event(event_type: &str, details: &str) {
let log_entry = json!({
"timestamp": chrono::Utc::now(),
"event_type": event_type,
"details": details,
"severity": "security"
});
// Log to security monitoring system
security_logger.log(&log_entry);
}use crate::observability::metrics;
// Track authentication attempts
metrics::counter("authentication_attempts_total",
&[("result", "success"), ("method", "api_key")]).inc();
// Track rate limiting
metrics::counter("rate_limit_blocks_total",
&[("ip", client_ip), ("endpoint", "auth")]).inc();fn check_security_alerts() {
let failed_attempts = get_failed_auth_attempts_last_minute();
if failed_attempts > 100 {
send_security_alert("High rate of authentication failures", &failed_attempts.to_string());
}
}- Use cryptographically secure random number generation
- Implement proper input validation and sanitization
- Use constant-time comparisons for sensitive data
- Implement rate limiting and account lockout
- Use secure session management
- Log security events appropriately
- Test security components thoroughly
- Follow the principle of least privilege
- Use placeholder authentication patterns
- Hardcode credentials or secrets
- Use weak random number generators
- Disclose sensitive information in error messages
- Skip input validation
- Use
unwrap()in production code - Log sensitive information
- Ignore security warnings
Before deploying code to production:
- All authentication methods are secure
- Input validation is implemented for all user inputs
- CSRF protection is enabled for state-changing operations
- Rate limiting is configured appropriately
- Security headers are set
- Error messages don't disclose sensitive information
- Cryptographic operations use secure algorithms
- Session management is secure
- Security tests pass
- Performance impact is acceptable
- Security monitoring is configured
- Security Integration Tests
- Security Regression Tests
- Security Performance Tests
- Security FixesModule
- Authentication Module
Security is a continuous process. This guide provides the foundation for secure development practices in Fortress. Always stay updated on the latest security threats and best practices, and regularly review and update security measures.
For questions or concerns about security implementation, consult the security team or refer to the security documentation.