freezone/portal-server/SECURITY_ROADMAP.md
2025-06-30 17:01:40 +02:00

485 lines
14 KiB
Markdown

# Portal Server Security Implementation Roadmap
## Overview
This roadmap outlines the prioritized implementation plan for enhancing the Portal Server's security posture. The recommendations are organized by priority and implementation complexity.
## Phase 1: Critical Security Fixes (Week 1-2)
### 🔴 P0: Webhook Signature Verification
**Status**: Critical Gap
**Effort**: 2-3 days
**Dependencies**: Add `hmac` and `sha2` crates
#### Implementation Plan
1. **Add Dependencies**
```toml
# Cargo.toml
hmac = "0.12"
sha2 = "0.10"
hex = "0.4"
```
2. **Implement Stripe Webhook Verification**
```rust
// src/services.rs
use hmac::{Hmac, Mac};
use sha2::Sha256;
impl StripeService {
pub fn verify_webhook_signature(&self, payload: &str, signature: &str, webhook_secret: &str) -> bool {
let elements: Vec<&str> = signature.split(',').collect();
let timestamp = elements.iter()
.find(|&&x| x.starts_with("t="))
.and_then(|x| x.strip_prefix("t="))
.and_then(|x| x.parse::<i64>().ok());
let signature_hash = elements.iter()
.find(|&&x| x.starts_with("v1="))
.and_then(|x| x.strip_prefix("v1="));
if let (Some(timestamp), Some(sig)) = (timestamp, signature_hash) {
let signed_payload = format!("{}.{}", timestamp, payload);
let mut mac = Hmac::<Sha256>::new_from_slice(webhook_secret.as_bytes()).unwrap();
mac.update(signed_payload.as_bytes());
let expected = hex::encode(mac.finalize().into_bytes());
expected == sig
} else {
false
}
}
}
```
3. **Implement Identify Webhook Verification**
```rust
// src/services.rs
impl IdentifyService {
pub fn verify_webhook_signature(&self, payload: &str, signature: &str) -> bool {
let mut mac = Hmac::<Sha256>::new_from_slice(self.webhook_secret.as_bytes()).unwrap();
mac.update(payload.as_bytes());
let expected = hex::encode(mac.finalize().into_bytes());
let provided = signature.trim_start_matches("sha256=");
expected == provided
}
}
```
### 🔴 P0: HTTPS Enforcement
**Status**: Missing
**Effort**: 1 day
**Dependencies**: TLS certificate configuration
#### Implementation Plan
1. **Add TLS Support**
```toml
# Cargo.toml
tokio-rustls = "0.24"
rustls-pemfile = "1.0"
```
2. **Configure HTTPS Server**
```rust
// src/server.rs
use tokio_rustls::{TlsAcceptor, rustls::ServerConfig as TlsConfig};
impl PortalServer {
pub async fn run_with_tls(self, cert_path: &str, key_path: &str) -> Result<()> {
let certs = load_certs(cert_path)?;
let key = load_private_key(key_path)?;
let config = TlsConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certs, key)?;
let acceptor = TlsAcceptor::from(Arc::new(config));
// Implement TLS server binding
}
}
```
## Phase 2: Authentication & Authorization (Week 3-4)
### 🟡 P1: API Key Authentication
**Status**: Not Implemented
**Effort**: 3-4 days
**Dependencies**: Database for API key storage
#### Implementation Plan
1. **Add API Key Model**
```rust
// src/models.rs
#[derive(Debug, Clone)]
pub struct ApiKey {
pub id: String,
pub key_hash: String,
pub name: String,
pub permissions: Vec<String>,
pub created_at: DateTime<Utc>,
pub expires_at: Option<DateTime<Utc>>,
pub last_used: Option<DateTime<Utc>>,
}
```
2. **Implement Authentication Middleware**
```rust
// src/middleware/auth.rs
use axum::{
extract::{Request, State},
http::{HeaderMap, StatusCode},
middleware::Next,
response::Response,
};
pub async fn api_key_auth(
State(state): State<AppState>,
headers: HeaderMap,
request: Request,
next: Next,
) -> Result<Response, StatusCode> {
let api_key = headers
.get("x-api-key")
.and_then(|v| v.to_str().ok())
.ok_or(StatusCode::UNAUTHORIZED)?;
if !state.validate_api_key(api_key).await {
return Err(StatusCode::UNAUTHORIZED);
}
Ok(next.run(request).await)
}
```
3. **Protected Route Configuration**
```rust
// src/server.rs
let protected_routes = Router::new()
.route("/api/kyc/create-verification-session", post(handlers::create_verification_session))
.route("/api/company/create-payment-intent", post(handlers::create_payment_intent))
.layer(middleware::from_fn_with_state(app_state.clone(), api_key_auth));
```
### 🟡 P1: Rate Limiting
**Status**: Not Implemented
**Effort**: 2-3 days
**Dependencies**: Redis for distributed rate limiting
#### Implementation Plan
1. **Add Rate Limiting Dependencies**
```toml
# Cargo.toml
tower-governor = "0.0.4"
redis = { version = "0.23", features = ["tokio-comp"] }
```
2. **Implement Rate Limiting**
```rust
// src/middleware/rate_limit.rs
use tower_governor::{GovernorLayer, GovernorConfigBuilder};
pub fn create_rate_limiter() -> GovernorLayer<'static, (), axum::extract::ConnectInfo<SocketAddr>> {
let governor_conf = GovernorConfigBuilder::default()
.per_second(10)
.burst_size(20)
.key_extractor(|req: &axum::extract::ConnectInfo<SocketAddr>| req.0.ip())
.finish()
.unwrap();
GovernorLayer::new(&governor_conf)
}
```
## Phase 3: Data Security (Week 5-6)
### 🟡 P1: Encrypted Database Storage
**Status**: Using In-Memory HashMap
**Effort**: 5-7 days
**Dependencies**: Database setup, encryption library
#### Implementation Plan
1. **Add Database Dependencies**
```toml
# Cargo.toml
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] }
aes-gcm = "0.10"
```
2. **Database Schema**
```sql
-- migrations/001_initial.sql
CREATE TABLE verification_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id VARCHAR NOT NULL UNIQUE,
user_id VARCHAR NOT NULL,
email_encrypted BYTEA NOT NULL,
status VARCHAR NOT NULL,
verification_data_encrypted BYTEA,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX idx_verification_sessions_user_id ON verification_sessions(user_id);
CREATE INDEX idx_verification_sessions_session_id ON verification_sessions(session_id);
```
3. **Encryption Service**
```rust
// src/services/encryption.rs
use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, NewAead}};
pub struct EncryptionService {
cipher: Aes256Gcm,
}
impl EncryptionService {
pub fn new(key: &[u8; 32]) -> Self {
let key = Key::from_slice(key);
let cipher = Aes256Gcm::new(key);
Self { cipher }
}
pub fn encrypt(&self, data: &str) -> Result<Vec<u8>, aes_gcm::Error> {
let nonce = Nonce::from_slice(b"unique nonce"); // Use random nonce in production
self.cipher.encrypt(nonce, data.as_bytes())
}
pub fn decrypt(&self, encrypted_data: &[u8]) -> Result<String, aes_gcm::Error> {
let nonce = Nonce::from_slice(b"unique nonce");
let decrypted = self.cipher.decrypt(nonce, encrypted_data)?;
Ok(String::from_utf8_lossy(&decrypted).to_string())
}
}
```
### 🟡 P2: Request Size Limits
**Status**: Not Implemented
**Effort**: 1 day
**Dependencies**: None
#### Implementation Plan
```rust
// src/server.rs
use tower_http::limit::RequestBodyLimitLayer;
router = router.layer(RequestBodyLimitLayer::new(1024 * 1024)); // 1MB limit
```
## Phase 4: Security Headers & Monitoring (Week 7-8)
### 🟡 P2: Security Headers
**Status**: Not Implemented
**Effort**: 2 days
**Dependencies**: None
#### Implementation Plan
```rust
// src/middleware/security_headers.rs
use axum::{
http::{header, HeaderValue},
response::Response,
};
use tower_http::set_header::SetResponseHeaderLayer;
pub fn security_headers_layer() -> tower::layer::util::Stack<
SetResponseHeaderLayer<HeaderValue>,
tower::layer::util::Stack<SetResponseHeaderLayer<HeaderValue>, tower::layer::Identity>
> {
tower::ServiceBuilder::new()
.layer(SetResponseHeaderLayer::overriding(
header::X_CONTENT_TYPE_OPTIONS,
HeaderValue::from_static("nosniff"),
))
.layer(SetResponseHeaderLayer::overriding(
header::X_FRAME_OPTIONS,
HeaderValue::from_static("DENY"),
))
.layer(SetResponseHeaderLayer::overriding(
header::STRICT_TRANSPORT_SECURITY,
HeaderValue::from_static("max-age=31536000; includeSubDomains"),
))
.into_inner()
}
```
### 🟡 P2: Security Monitoring
**Status**: Basic Logging Only
**Effort**: 3-4 days
**Dependencies**: Prometheus, Grafana
#### Implementation Plan
1. **Add Monitoring Dependencies**
```toml
# Cargo.toml
prometheus = "0.13"
lazy_static = "1.4"
```
2. **Security Metrics**
```rust
// src/metrics.rs
use prometheus::{Counter, Histogram, register_counter, register_histogram};
lazy_static! {
pub static ref AUTH_FAILURES: Counter = register_counter!(
"auth_failures_total",
"Total number of authentication failures"
).unwrap();
pub static ref WEBHOOK_VERIFICATION_FAILURES: Counter = register_counter!(
"webhook_verification_failures_total",
"Total number of webhook verification failures"
).unwrap();
pub static ref RATE_LIMIT_VIOLATIONS: Counter = register_counter!(
"rate_limit_violations_total",
"Total number of rate limit violations"
).unwrap();
}
```
## Phase 5: Compliance & Testing (Week 9-10)
### 🟡 P2: Security Testing Framework
**Status**: Not Implemented
**Effort**: 4-5 days
**Dependencies**: Testing tools
#### Implementation Plan
1. **Add Security Testing Dependencies**
```toml
# Cargo.toml
[dev-dependencies]
cargo-audit = "0.18"
cargo-deny = "0.14"
```
2. **Security Test Suite**
```rust
// tests/security_tests.rs
#[tokio::test]
async fn test_cors_restrictions() {
// Test CORS policy enforcement
}
#[tokio::test]
async fn test_webhook_signature_verification() {
// Test webhook signature validation
}
#[tokio::test]
async fn test_rate_limiting() {
// Test rate limiting enforcement
}
#[tokio::test]
async fn test_input_validation() {
// Test input sanitization
}
```
3. **Automated Security Scanning**
```bash
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
- name: Security Audit
run: cargo audit
- name: Dependency Check
run: cargo deny check
```
## Implementation Timeline
```mermaid
gantt
title Portal Server Security Implementation
dateFormat YYYY-MM-DD
section Phase 1: Critical
Webhook Verification :crit, p1-1, 2025-06-30, 3d
HTTPS Enforcement :crit, p1-2, 2025-07-02, 1d
section Phase 2: Auth
API Key Authentication :p2-1, 2025-07-03, 4d
Rate Limiting :p2-2, 2025-07-07, 3d
section Phase 3: Data
Database Storage :p3-1, 2025-07-10, 7d
Request Limits :p3-2, 2025-07-17, 1d
section Phase 4: Headers
Security Headers :p4-1, 2025-07-18, 2d
Security Monitoring :p4-2, 2025-07-20, 4d
section Phase 5: Testing
Security Testing :p5-1, 2025-07-24, 5d
```
## Success Criteria
### Phase 1 Completion
- [ ] All webhook signatures properly verified
- [ ] HTTPS enforced in production
- [ ] No critical security vulnerabilities
### Phase 2 Completion
- [ ] API key authentication implemented
- [ ] Rate limiting active on all endpoints
- [ ] Authentication bypass attempts blocked
### Phase 3 Completion
- [ ] All sensitive data encrypted at rest
- [ ] Database storage implemented
- [ ] Request size limits enforced
### Phase 4 Completion
- [ ] Security headers implemented
- [ ] Security metrics collection active
- [ ] Monitoring dashboards deployed
### Phase 5 Completion
- [ ] Automated security testing in CI/CD
- [ ] Security documentation complete
- [ ] Penetration testing passed
## Risk Mitigation
### High-Risk Scenarios
1. **API Key Compromise**: Implement key rotation, monitoring
2. **Database Breach**: Encryption at rest, access controls
3. **DDoS Attack**: Rate limiting, CDN protection
4. **Insider Threat**: Audit logging, access controls
### Rollback Plans
- Each phase includes rollback procedures
- Feature flags for gradual rollout
- Database migration rollback scripts
- Configuration rollback procedures
## Resource Requirements
### Development Resources
- **Senior Security Engineer**: 40 hours/week for 10 weeks
- **Backend Developer**: 20 hours/week for 10 weeks
- **DevOps Engineer**: 10 hours/week for 10 weeks
### Infrastructure Requirements
- **Database**: PostgreSQL with encryption
- **Monitoring**: Prometheus + Grafana
- **Security Tools**: SIEM, vulnerability scanner
- **Testing Environment**: Isolated security testing environment
---
**Document Version**: 1.0
**Last Updated**: 2025-06-29
**Owner**: Security Team
**Review Cycle**: Monthly