# Security Charybdis provides enterprise-grade security with mTLS authentication and RBAC authorization. ## Overview ```mermaid graph TB A[Client Request] -->|mTLS Handshake| B[TLS Layer] B -->|Certificate| C[Auth Interceptor] C -->|Extract Identity| D{Parse Certificate} D -->|CN, OU, O| E[Role Mapping] E -->|Role| F{Permission Check} F -->|Authorized| G[Entity Service] F -->|Denied| H[PermissionDenied Error] G -->|Audit Log| I[Security Events] style C fill:#f9d71c,stroke:#f9a825 style F fill:#4A90E2,stroke:#2E5C8A ``` ## mTLS Authentication Mutual TLS (mTLS) provides certificate-based client authentication. ### How It Works 1. **Client** presents X.509 certificate during TLS handshake 2. **Server** validates certificate against trusted CA 3. **Charybdis** extracts certificate identity (CN, OU, O) 4. **RBAC Engine** maps identity to role 5. **Permissions** are checked before allowing the request ### Certificate Structure ``` Subject: CN=admin-user, OU=platform-team, O=Charybdis-Dev, C=US Issuer: CN=Charybdis Root CA, O=Charybdis-Dev, C=US Validity: Not Before: Nov 3 2025, Not After: Nov 3 2026 ``` **Fields Used for Authentication**: - `CN` (Common Name) - User or service identifier - `OU` (Organizational Unit) - Team or role identifier - `O` (Organization) - Organization name ## Configuration ### Environment Variables ```bash # Enable mTLS export SECURITY_MTLS_ENABLED=true # Server certificate and key export SECURITY_MTLS_SERVER_CERT=./certs/server-cert.pem export SECURITY_MTLS_SERVER_KEY=./certs/server-key.pem # Client CA for verification export SECURITY_MTLS_CLIENT_CA=./certs/ca.pem # Enable RBAC export SECURITY_RBAC_ENABLED=true ``` ### Generating Certificates #### Development Certificates Use the provided dev-cert script: ```bash ./deploy/scripts/generate-dev-certs.sh ``` This generates (under `deploy/certs/`): - `ca.pem` / `ca-key.pem` — Certificate Authority - `server-cert.pem` / `server-key.pem` — Server certificate - `admin-cert.pem` / `admin-key.pem` — Admin client (OU=platform-team) - Per-role client certs (OU=automation, OU=plugins) For an individual client cert without regenerating everything, use `./deploy/scripts/generate-client-cert.sh`. #### Production Certificates For production, use a proper PKI: **Options**: - **Internal PKI**: HashiCorp Vault, cert-manager, step-ca - **Public CA**: Let's Encrypt (for internet-facing) - **Enterprise CA**: Your organization's certificate authority **Requirements**: - Valid for at least 90 days - Issued by trusted CA - Proper subject alternative names (SANs) - Appropriate key usage extensions ### Certificate Best Practices ✅ **DO**: - Use short-lived certificates (24-90 days) - Implement automatic rotation - Monitor expiration dates - Use strong key lengths (2048+ bit RSA or 256+ bit ECC) - Store private keys securely - Use separate CAs for dev/prod ❌ **DON'T**: - Use self-signed certs in production - Share private keys - Use the same certificate across environments - Ignore expiration warnings - Store keys in version control ## RBAC Authorization Role-Based Access Control (RBAC) enforces fine-grained permissions. ### Role Mapping Charybdis maps certificate attributes to roles: ``` Certificate OU → RBAC Role → Permissions ``` ### Default Roles | Role | Certificate OU | Description | Permissions | |------|---------------|-------------|-------------| | `platform` | `platform-team` | Platform administrators | Full access (CRUD + list) | | `automation` | `automation` | CI/CD pipelines | Create, read, update, list | | `plugin` | `plugins` | Integration plugins | Read, list only | ### Permissions | Permission | Methods | Description | |------------|---------|-------------| | `entity:create` | CreateEntity | Create new entities | | `entity:read` | GetEntity | Read entity by ID | | `entity:update` | UpdateEntity, PartialUpdateEntity | Modify entities | | `entity:delete` | DeleteEntity | Delete entities | | `entity:list` | ListEntities | List all entities | ### Permission Matrix | Role | Create | Read | Update | Delete | List | |------|--------|------|--------|--------|------| | `platform` | ✅ | ✅ | ✅ | ✅ | ✅ | | `automation` | ✅ | ✅ | ✅ | ❌ | ✅ | | `plugin` | ❌ | ✅ | ❌ | ❌ | ✅ | ## Usage Examples ### Admin Access (Full Permissions) ```bash # Create entity grpcurl \ -cacert certs/ca.pem \ -cert certs/admin-cert.pem \ -key certs/admin-key.pem \ -d '{"entity": {...}}' \ localhost:50051 charybdis.entities.EntityService/CreateEntity # ✅ SUCCESS ``` ### Automation Access (Limited) ```bash # CI/CD can create grpcurl \ -cacert certs/ca.pem \ -cert certs/ci-pipeline-cert.pem \ -key certs/ci-pipeline-key.pem \ -d '{"entity": {...}}' \ localhost:50051 charybdis.entities.EntityService/CreateEntity # ✅ SUCCESS # But cannot delete grpcurl \ -cacert certs/ca.pem \ -cert certs/ci-pipeline-cert.pem \ -key certs/ci-pipeline-key.pem \ -d '{"id": "..."}' \ localhost:50051 charybdis.entities.EntityService/DeleteEntity # ❌ Code: PermissionDenied # Message: Role 'automation' does not have permission 'entity:delete' ``` ### Plugin Access (Read-Only) ```bash # Plugin can list grpcurl \ -cacert certs/ca.pem \ -cert certs/defectdojo-plugin-cert.pem \ -key certs/defectdojo-plugin-key.pem \ -d '{}' \ localhost:50051 charybdis.entities.EntityService/ListEntities # ✅ SUCCESS # But cannot create grpcurl \ -cacert certs/ca.pem \ -cert certs/defectdojo-plugin-cert.pem \ -key certs/defectdojo-plugin-key.pem \ -d '{"entity": {...}}' \ localhost:50051 charybdis.entities.EntityService/CreateEntity # ❌ Code: PermissionDenied # Message: Role 'plugin' does not have permission 'entity:create' ``` ## Custom Role Configuration ### Defining Custom Roles Edit `src/main.rs::setup_default_rbac_config()`: ```rust let role_mappings = vec![ // Custom developer role RoleMapping { role: "developer".to_string(), rules: vec![RoleRule { subject: SubjectMatch { cn: None, ou: Some("engineering".to_string()), o: None, }, }], }, ]; let mut permissions = HashMap::new(); permissions.insert( "developer".to_string(), vec![ "entity:create".to_string(), "entity:read".to_string(), "entity:list".to_string(), ], ); ``` ### Certificate-Based Mapping Map specific certificates to roles: ```rust // Map by CN (specific user/service) RoleRule { subject: SubjectMatch { cn: Some("jenkins-ci".to_string()), ou: None, o: None, }, } // Map by Organization RoleRule { subject: SubjectMatch { cn: None, ou: None, o: Some("External-Partner".to_string()), }, } // Combined matching RoleRule { subject: SubjectMatch { cn: Some("admin".to_string()), ou: Some("platform-team".to_string()), o: Some("MyCompany".to_string()), }, } ``` ## Audit Logging All security events are logged for compliance and forensics. ### Event Types | Event | Logged Information | |-------|-------------------| | Authentication Success | Identity (CN, OU, O), timestamp | | Authentication Failure | Reason, timestamp | | Authorization Success | Identity, role, method, duration | | Authorization Denial | Identity, role, method, required permission | | Certificate Error | Error details, certificate info | ### Log Format ``` 2025-11-04T10:16:22Z INFO [AUDIT] Authorization Success identity: CN=admin-user, OU=platform-team role: platform method: /charybdis.entities.EntityService/CreateEntity permission: entity:create duration: 0.08ms 2025-11-04T10:16:25Z WARN [AUDIT] Authorization Denied identity: CN=defectdojo-plugin, OU=plugins role: plugin method: /charybdis.entities.EntityService/CreateEntity required_permission: entity:create reason: Role 'plugin' does not have permission 'entity:create' duration: 0.05ms ``` ### Audit Configuration ```bash # Enable audit logging (default: true) export SECURITY_RBAC_AUDIT_ENABLED=true # Log all requests (default: true) export SECURITY_RBAC_AUDIT_LOG_ALL_REQUESTS=true # Log denied requests (default: true) export SECURITY_RBAC_AUDIT_LOG_DENIED=true ``` ## Reverse Proxy Deployment For environments where mTLS termination happens at a reverse proxy: ### Architecture ```mermaid graph LR A[Client] -->|mTLS| B[Reverse Proxy] B -->|HTTP + Cert Header| C[Charybdis] style B fill:#4A90E2,stroke:#2E5C8A ``` ### Proxy Configuration #### Envoy ```yaml - name: envoy.filters.http.lua typed_config: inline_code: | function envoy_on_request(request_handle) local cert = request_handle:connection():ssl():peerCertificatePresented() if cert then request_handle:headers():add("x-client-cert", cert) end end ``` #### nginx ```nginx location / { proxy_set_header X-Client-Cert $ssl_client_cert; proxy_pass http://charybdis:50051; } ``` ### Header Format Charybdis accepts certificates in these headers: - `x-forwarded-client-cert` (Envoy/Istio standard) - `x-client-cert` (nginx) Format: Base64-encoded DER certificate ## Troubleshooting ### Common Issues #### 1. Certificate Not Found ``` ERROR: Client certificate required but not provided ``` **Causes**: - Certificate not sent by client - Wrong certificate path - Certificate expired **Solutions**: ```bash # Verify certificate is valid openssl x509 -in cert.pem -noout -text # Check expiration openssl x509 -in cert.pem -noout -dates # Test TLS handshake openssl s_client -connect localhost:50051 \ -CAfile ca.pem -cert cert.pem -key key.pem ``` #### 2. Permission Denied ``` Code: PermissionDenied Message: Role 'X' does not have permission 'Y' ``` **Causes**: - Certificate OU doesn't match any role - Role lacks required permission **Solutions**: ```bash # Check certificate attributes openssl x509 -in cert.pem -noout -subject # Review role mappings in src/main.rs # Verify permission requirements in docs ``` #### 3. No Role Assigned ``` ERROR: No role assigned to identity: CN=..., OU=... ``` **Causes**: - Certificate OU not configured in role mappings - Typo in OU value **Solutions**: - Add role mapping for the OU - Generate new certificate with correct OU - Check role mapping configuration ## Security Hardening ### Production Checklist - [ ] Use certificates from trusted CA - [ ] Enable mTLS (`SECURITY_MTLS_ENABLED=true`) - [ ] Enable RBAC (`SECURITY_RBAC_ENABLED=true`) - [ ] Implement certificate rotation (90 days max) - [ ] Monitor certificate expiration - [ ] Enable audit logging - [ ] Use TLS 1.3 only - [ ] Implement rate limiting - [ ] Set up intrusion detection - [ ] Regular security audits ### Certificate Rotation Implement automatic rotation: ```bash #!/bin/bash # rotate-certs.sh # Generate new certificate ./generate-cert.sh # Gracefully restart Charybdis kill -HUP $(pidof charybdis) # Verify new cert is active sleep 5 openssl s_client -connect localhost:50051 < /dev/null | \ openssl x509 -noout -dates ``` ### Monitoring Monitor security metrics: - Authentication success/failure rate - Authorization denial rate - Certificate expiration warnings - Audit log anomalies - Failed login attempts ## Compliance Charybdis security features support compliance requirements: | Standard | Supported Features | |----------|-------------------| | **SOC 2** | Audit logging, access control, encryption in transit | | **ISO 27001** | Authentication, authorization, audit trails | | **PCI DSS** | Encryption, access control, logging | | **HIPAA** | Access control, audit logging, encryption | ## Next Steps - [Plugins](../plugins/README.md) — configure plugins to use mTLS client certs - [Architecture](architecture.md) — interceptor placement and observability hooks --- **Security Questions?** Open an issue (for vulnerabilities, use private disclosure).