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