# 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::().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::::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::::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, pub created_at: DateTime, pub expires_at: Option>, pub last_used: Option>, } ``` 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, headers: HeaderMap, request: Request, next: Next, ) -> Result { 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> { let governor_conf = GovernorConfigBuilder::default() .per_second(10) .burst_size(20) .key_extractor(|req: &axum::extract::ConnectInfo| 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, 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 { 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, tower::layer::util::Stack, 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