Files
charybdis/docs/security.md
T
Guillaume GRABÉ f1b1543f29
CI / Check (push) Successful in 13m13s
CI / Format (push) Successful in 48s
CI / Clippy (push) Successful in 12m13s
CI / Test (push) Successful in 12m45s
doc: update and cleanup
2026-06-09 11:26:47 +02:00

505 lines
12 KiB
Markdown

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