Files
charybdis/plugins/defectdojo/README.md
T
2026-05-12 17:06:43 +02:00

302 lines
8.1 KiB
Markdown

# DefectDojo Plugin for Charybdis
Event-driven plugin that synchronizes Charybdis entities with DefectDojo security testing platform.
## Overview
The DefectDojo plugin automatically provisions and manages resources in DefectDojo based on entity lifecycle events in Charybdis. It provides bidirectional mapping between Charybdis entities and DefectDojo resources.
## Supported Resources
| Charybdis Entity | DefectDojo Resource | Trigger |
|-----------------|---------------------|---------|
| Component | Product | Create/Update/Delete Component |
| User | User | Create/Update/Delete User |
| System | Product Type | Create/Update/Delete System |
| Group | Product Member | Create/Update/Delete Group with annotation |
| Resource | Engagement | Create/Update/Delete Resource with annotation |
## Configuration
Add the DefectDojo plugin configuration to your `config.toml`:
```toml
[plugins.defectdojo]
enabled = true
base_url = "${DEFECTDOJO_URL}"
api_token = "${DEFECTDOJO_API_TOKEN}"
default_product_type_id = 1
auto_create_users = true
auto_create_product_types = false
```
### Environment Variables
- `DEFECTDOJO_URL`: Base URL of your DefectDojo instance (e.g., `https://defectdojo.example.com`)
- `DEFECTDOJO_API_TOKEN`: API token for authentication
### Field Mappings
Define how Charybdis entity fields map to DefectDojo API fields:
```toml
[plugins.defectdojo.field_mappings.product]
name = "metadata.name"
description = "metadata.description"
business_criticality = { value = "high" }
product_type_id = { value = 1 }
```
#### Mapping Types
1. **Direct field mapping**: `"metadata.name"` - Extract field from entity
2. **Static value**: `{ value = "high" }` - Use static value
3. **Entity resolution**: Resolve entity references
```toml
product_manager = {
from = "spec.owner",
resolve_entity = "User",
extract = "annotations.defectdojo.com/user-id"
}
```
## Usage Examples
### 1. Create a Product from Component
```yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Payment processing service
tags:
- payment
- critical
spec:
type: service
lifecycle: production
owner: platform-team
```
When this Component is created in Charybdis, the plugin automatically:
1. Creates a Product in DefectDojo
2. Stores the DefectDojo product ID in annotations: `defectdojo.com/product-id`
### 2. Create Users
```yaml
apiVersion: backstage.io/v1alpha1
kind: User
metadata:
name: john.doe
spec:
profile:
displayName: John Doe
email: john.doe@example.com
memberOf:
- platform-team
```
The plugin creates a DefectDojo user and stores the user ID in annotations.
### 3. Add Product Members
Create a Group entity with a special annotation to trigger product member creation:
```yaml
apiVersion: backstage.io/v1alpha1
kind: Group
metadata:
name: payment-service-security-team
annotations:
defectdojo.com/product-member: "true"
spec:
type: team
parent: component:payment-service # Reference to Component
members:
- user:john.doe
- user:jane.smith
```
The plugin resolves:
- `parent` → Component → DefectDojo Product ID
- `members` → Users → DefectDojo User IDs
- Creates Product Member entries with specified role
### 4. Create Engagements
```yaml
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: payment-service-q1-security-assessment
annotations:
defectdojo.com/engagement: "true"
version: "2.1.0"
commit_hash: "abc123"
spec:
type: security-assessment
owner: component:payment-service
dependsOn:
- user:john.doe # Lead
target_start: "2025-01-01"
target_end: "2025-03-31"
```
## Annotations
The plugin uses annotations to:
1. **Store DefectDojo IDs** (auto-managed):
- `defectdojo.com/product-id`
- `defectdojo.com/user-id`
- `defectdojo.com/product-type-id`
- `defectdojo.com/product-member-id`
- `defectdojo.com/engagement-id`
2. **Trigger special behaviors**:
- `defectdojo.com/product-member: "true"` - Create product members from Group
- `defectdojo.com/engagement: "true"` - Create engagement from Resource
## Entity Resolution
The plugin supports complex field mappings that resolve entity references:
```toml
[plugins.defectdojo.field_mappings.product]
product_manager = {
from = "spec.owner", # Get owner field from entity
resolve_entity = "User", # Resolve as User entity
extract = "annotations.defectdojo.com/user-id" # Extract DD user ID
}
```
This allows you to reference Users by entity ID in Charybdis, and the plugin automatically resolves to DefectDojo user IDs.
### Array Resolution
For resolving arrays of entities (like group members):
```toml
user_id = {
from = "spec.members",
resolve_entity = "User",
extract = "annotations.defectdojo.com/user-id",
resolve_array = true
}
```
## Architecture
```
┌─────────────────┐
│ Charybdis │
│ (gRPC API) │
└────────┬────────┘
│ Entity Events
┌─────────────────┐
│ Event Dispatcher│
└────────┬────────┘
┌─────────────────────────────┐
│ DefectDojo Plugin │
│ ┌────────────────────────┐ │
│ │ ProductHandler │ │
│ │ UserHandler │ │
│ │ ProductTypeHandler │ │
│ │ ProductMemberHandler │ │
│ │ EngagementHandler │ │
│ └────────────────────────┘ │
└──────────┬──────────────────┘
│ HTTP API
┌─────────────────┐
│ DefectDojo │
│ (REST API) │
└─────────────────┘
```
## Resource Handlers
Each resource handler implements:
- `handle_create()`: Create resource in DefectDojo when entity created
- `handle_update()`: Update resource in DefectDojo when entity updated
- `handle_delete()`: Delete/deactivate resource in DefectDojo when entity deleted
## Error Handling
- Failed API calls are logged with full error details
- Entity is still created/updated in Charybdis even if DefectDojo sync fails
- Missing DefectDojo IDs trigger automatic creation
- User deletion deactivates users instead of deleting (DefectDojo best practice)
## Development
### Building
```bash
cargo build
```
### Testing
```bash
cargo test
```
### Adding New Resource Types
1. Create new handler in `src/handlers/`
2. Implement `ResourceHandler` trait
3. Add handler to plugin in `src/lib.rs`
4. Define field mappings in config
## API Reference
### DefectDojo API Endpoints Used
- `POST /api/v2/products/` - Create product
- `PUT /api/v2/products/{id}/` - Update product
- `DELETE /api/v2/products/{id}/` - Delete product
- `POST /api/v2/users/` - Create user
- `PUT /api/v2/users/{id}/` - Update user
- `POST /api/v2/product_types/` - Create product type
- `POST /api/v2/product_members/` - Create product member
- `DELETE /api/v2/product_members/{id}/` - Remove product member
- `POST /api/v2/engagements/` - Create engagement
- `PUT /api/v2/engagements/{id}/` - Update engagement
## Security
- API token should be stored in environment variables, not committed to git
- Use mTLS for Charybdis gRPC connections
- DefectDojo HTTPS endpoint recommended for production
## Troubleshooting
### Entity not syncing to DefectDojo
1. Check plugin is enabled in `config.toml`
2. Verify `DEFECTDOJO_API_TOKEN` is set
3. Check entity kind matches handler trigger kinds
4. Review logs for API errors
### Missing DefectDojo IDs
If annotations are missing:
- Plugin will attempt to create resource on next update
- Check for errors in creation logs
- Verify field mappings provide required fields
### User already exists errors
- Plugin checks for existing users by email before creating
- Will reuse existing user ID instead of creating duplicate
## License
Part of Charybdis project.