12 KiB
Security
Charybdis provides enterprise-grade security with mTLS authentication and RBAC authorization.
Overview
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
- Client presents X.509 certificate during TLS handshake
- Server validates certificate against trusted CA
- Charybdis extracts certificate identity (CN, OU, O)
- RBAC Engine maps identity to role
- 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 identifierOU(Organizational Unit) - Team or role identifierO(Organization) - Organization name
Configuration
Environment Variables
# 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:
./deploy/scripts/generate-dev-certs.sh
This generates (under deploy/certs/):
ca.pem/ca-key.pem— Certificate Authorityserver-cert.pem/server-key.pem— Server certificateadmin-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)
# 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)
# 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)
# 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():
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:
// 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
# 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
graph LR
A[Client] -->|mTLS| B[Reverse Proxy]
B -->|HTTP + Cert Header| C[Charybdis]
style B fill:#4A90E2,stroke:#2E5C8A
Proxy Configuration
Envoy
- 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
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:
# 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:
# 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:
#!/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 — configure plugins to use mTLS client certs
- Architecture — interceptor placement and observability hooks
Security Questions? Open an issue (for vulnerabilities, use private disclosure).