8.1 KiB
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:
[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:
[plugins.defectdojo.field_mappings.product]
name = "metadata.name"
description = "metadata.description"
business_criticality = { value = "high" }
product_type_id = { value = 1 }
Mapping Types
- Direct field mapping:
"metadata.name"- Extract field from entity - Static value:
{ value = "high" }- Use static value - Entity resolution: Resolve entity references
product_manager = { from = "spec.owner", resolve_entity = "User", extract = "annotations.defectdojo.com/user-id" }
Usage Examples
1. Create a Product from Component
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:
- Creates a Product in DefectDojo
- Stores the DefectDojo product ID in annotations:
defectdojo.com/product-id
2. Create Users
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:
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 IDmembers→ Users → DefectDojo User IDs- Creates Product Member entries with specified role
4. Create Engagements
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:
-
Store DefectDojo IDs (auto-managed):
defectdojo.com/product-iddefectdojo.com/user-iddefectdojo.com/product-type-iddefectdojo.com/product-member-iddefectdojo.com/engagement-id
-
Trigger special behaviors:
defectdojo.com/product-member: "true"- Create product members from Groupdefectdojo.com/engagement: "true"- Create engagement from Resource
Entity Resolution
The plugin supports complex field mappings that resolve entity references:
[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):
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 createdhandle_update(): Update resource in DefectDojo when entity updatedhandle_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
cargo build
Testing
cargo test
Adding New Resource Types
- Create new handler in
src/handlers/ - Implement
ResourceHandlertrait - Add handler to plugin in
src/lib.rs - Define field mappings in config
API Reference
DefectDojo API Endpoints Used
POST /api/v2/products/- Create productPUT /api/v2/products/{id}/- Update productDELETE /api/v2/products/{id}/- Delete productPOST /api/v2/users/- Create userPUT /api/v2/users/{id}/- Update userPOST /api/v2/product_types/- Create product typePOST /api/v2/product_members/- Create product memberDELETE /api/v2/product_members/{id}/- Remove product memberPOST /api/v2/engagements/- Create engagementPUT /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
- Check plugin is enabled in
config.toml - Verify
DEFECTDOJO_API_TOKENis set - Check entity kind matches handler trigger kinds
- 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.