Files
charybdis/plugins/defectdojo
Guillaume GRABÉ 3e2b361cf6
CI / Clippy (push) Failing after 5m27s
CI / Check (push) Failing after 6m36s
CI / Format (push) Failing after 51s
CI / Test (push) Failing after 6m41s
fix: remove openssl dependency
2026-06-08 21:24:35 +02:00
..
2026-05-12 17:06:43 +02:00
2026-05-12 17:06:43 +02:00
2026-05-12 17:06:43 +02:00
2026-06-08 21:24:35 +02:00
2026-05-12 17:06:43 +02:00

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

  1. Direct field mapping: "metadata.name" - Extract field from entity
  2. Static value: { value = "high" } - Use static value
  3. 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:

  1. Creates a Product in DefectDojo
  2. 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 ID
  • members → 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:

  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:

[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 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

cargo build

Testing

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.