Public Access
505 lines
12 KiB
Markdown
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).
|