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

14 KiB

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

    # Cargo.toml
    hmac = "0.12"
    sha2 = "0.10"
    hex = "0.4"
    
  2. Implement Stripe Webhook Verification

    // 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

    // 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

    # Cargo.toml
    tokio-rustls = "0.24"
    rustls-pemfile = "1.0"
    
  2. Configure HTTPS Server

    // 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

    // 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

    // 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

    // 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

    # Cargo.toml
    tower-governor = "0.0.4"
    redis = { version = "0.23", features = ["tokio-comp"] }
    
  2. Implement Rate Limiting

    // 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

    # Cargo.toml
    sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] }
    aes-gcm = "0.10"
    
  2. Database Schema

    -- 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

    // 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

// 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

// 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

    # Cargo.toml
    prometheus = "0.13"
    lazy_static = "1.4"
    
  2. Security Metrics

    // 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

    # Cargo.toml
    [dev-dependencies]
    cargo-audit = "0.18"
    cargo-deny = "0.14"
    
  2. Security Test Suite

    // 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

    # .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

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