diff --git a/docs/assets/images/pro_dashboard_v2_add_widget.png b/docs/assets/images/pro_dashboard_v2_add_widget.png new file mode 100644 index 00000000000..4f59fea2f67 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_add_widget.png differ diff --git a/docs/assets/images/pro_dashboard_v2_default.png b/docs/assets/images/pro_dashboard_v2_default.png new file mode 100644 index 00000000000..a43bc6192c0 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_default.png differ diff --git a/docs/assets/images/pro_dashboard_v2_edit_grid.png b/docs/assets/images/pro_dashboard_v2_edit_grid.png new file mode 100644 index 00000000000..23e70dfc4bc Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_edit_grid.png differ diff --git a/docs/assets/images/pro_dashboard_v2_empty_state.png b/docs/assets/images/pro_dashboard_v2_empty_state.png new file mode 100644 index 00000000000..e93a25aced1 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_empty_state.png differ diff --git a/docs/assets/images/pro_dashboard_v2_home.png b/docs/assets/images/pro_dashboard_v2_home.png new file mode 100644 index 00000000000..b5487472c36 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_home.png differ diff --git a/docs/assets/images/pro_dashboard_v2_manage_layouts.png b/docs/assets/images/pro_dashboard_v2_manage_layouts.png new file mode 100644 index 00000000000..76141fe6ac4 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_manage_layouts.png differ diff --git a/docs/assets/images/pro_dashboard_v2_widget_config.png b/docs/assets/images/pro_dashboard_v2_widget_config.png new file mode 100644 index 00000000000..2296690b049 Binary files /dev/null and b/docs/assets/images/pro_dashboard_v2_widget_config.png differ diff --git a/docs/content/asset_modelling/OS_hierarchy/OS__sla_configuration.md b/docs/content/asset_modelling/OS_hierarchy/OS__sla_configuration.md index b0c82fd1e1d..8a8d9edb33d 100644 --- a/docs/content/asset_modelling/OS_hierarchy/OS__sla_configuration.md +++ b/docs/content/asset_modelling/OS_hierarchy/OS__sla_configuration.md @@ -21,7 +21,7 @@ You can use SLAs as a way to represent your organizations remediation policies. * You can sort or filter Finding tables by SLA days. * SLA violations can be configured to trigger [Notifications](/admin/notifications/about_notifications/) to DefectDojo users assigned to the related Product. * In **DefectDojo Pro**, SLA performance is also tracked on the [Executive Insights and Remediation](/metrics_reports/pro_metrics/pro__overview/) Metrics Dashboards. -* SLA compliance can also be used to create custom [Dashboard Tiles](/metrics_reports/dashboards/about_custom_dashboard_tiles/#sla-violation-tile) in **DefectDojo Pro**. +* SLA compliance can also be surfaced on a custom [dashboard](/metrics_reports/dashboards/custom-dashboards/) in **DefectDojo Pro** β€” for example with an SLA Burndown or a filtered Count widget. ### Mitigated Within SLA status diff --git a/docs/content/asset_modelling/PRO_hierarchy/priority_sla.md b/docs/content/asset_modelling/PRO_hierarchy/priority_sla.md index f09c98fa6f4..f6936bd5960 100644 --- a/docs/content/asset_modelling/PRO_hierarchy/priority_sla.md +++ b/docs/content/asset_modelling/PRO_hierarchy/priority_sla.md @@ -218,7 +218,7 @@ You can use SLAs as a way to represent your organizations remediation policies. * You can sort or filter Finding tables by SLA days. * SLA violations can be configured to trigger [Notifications](/admin/notifications/about_notifications/) to DefectDojo users assigned to the related Product. * In **DefectDojo Pro**, SLA performance is also tracked on the [Executive Insights and Remediation](/metrics_reports/pro_metrics/pro__overview/) Metrics Dashboards. -* SLA compliance can also be used to create custom [Dashboard Tiles](/metrics_reports/dashboards/about_custom_dashboard_tiles/#sla-violation-tile) in **DefectDojo Pro**. +* SLA compliance can also be surfaced on a custom [dashboard](/metrics_reports/dashboards/custom-dashboards/) in **DefectDojo Pro** β€” for example with an SLA Burndown or a filtered Count widget. ### Mitigated Within SLA status diff --git a/docs/content/metrics_reports/dashboards/Introduction_dashboard.md b/docs/content/metrics_reports/dashboards/Introduction_dashboard.md index 288bfbe7444..ff566df4d3e 100644 --- a/docs/content/metrics_reports/dashboards/Introduction_dashboard.md +++ b/docs/content/metrics_reports/dashboards/Introduction_dashboard.md @@ -2,6 +2,7 @@ title: "DefectDojo Main Dashboard" description: "Working with the front page of DefectDojo" weight: 1 +audience: opensource aliases: - /en/customize_dojo/dashboards/Introduction_dashboard - /en/customize_dojo/dashboards/pro_dashboards @@ -15,7 +16,7 @@ The Dashboard is likely the first page you'll see when you open DefectDojo. It s
-![image](images/Introduction_to_Dashboard_Features.png) +> **πŸ’‘ DefectDojo Pro:** In DefectDojo Pro, the home page is a fully **customizable dashboard** β€” you build it from widgets and arrange them yourself, rather than using the fixed layout described below. See **[Customizable Dashboards](../custom-dashboards/)** for the concepts and a UI walkthrough. The rest of this page describes the open-source Main Dashboard.
@@ -55,92 +56,3 @@ Superusers can toggle which charts appear on the dashboard. Navigate to the gear Select **Reset Dashboard Configuration** from the same menu to restore defaults. -
- -## Dashboard Components - -* **Customizable Dashboard Tiles**, which you can use to visualize the metrics which are relevant to you. -* **Pre\-built Dashboard Charts**, which visualize your team’s overall performance. - -Each team member shares a single dashboard, but the results of the dashboard are restricted by their role and Product Membership. Team members will only see calculated stats for the Products, Engagements, Findings or other objects that they have access to. For more information, see our guides on [User Permissions and Roles](/admin/user_management/about_perms_and_roles). - -### Dashboard Tiles - -Tiles are designed to provide relevant information and speed up navigation within DefectDojo. - -![image](images/Introduction_to_Dashboard_Features_2.png) - -Tiles can: - -* Act as shortcuts for particular sets of Findings, Products, or other objects -* Visualize metrics related to your Product -* Provide alerts on particular activity, track SLA Violations, failing imports or new Critical Findings - -Tiles are pinned to the top section of your **🏠 Home** page. - -To learn how to add and use dashboard tiles, see our [guide](/metrics_reports/dashboards/about_custom_dashboard_tiles). - -### Dashboard Charts - -Located beneath Dashboard Tiles, DefectDojo has five pre\-built charts: - -* **Historical Finding Severity** pie\-chart -* **Reported Finding Severity** histogram, by month -* **Unassigned Answered Engagement Questionnaires** table -* **Top 10 Graded Products** table -* **Bottom 10 Graded Products** table - -These charts can be added or removed from the dashboard via **Dashboard Configuration**. - -#### Historical Finding Severity - -This chart organizes all Findings created in DefectDojo by Severity, so that you can see the overall distribution of vulnerability levels in your environment. - -![image](images/Introduction_to_Dashboard_Features_3.png) - -#### Reported Finding Severity - -This chart allows you to monitor the volume and severity distribution of incoming Findings per month. - -![image](images/Introduction_to_Dashboard_Features_4.png) - -#### Unassigned Answered Engagement Questionnaires - -If you have completed Engagement Questionnaires for review, those will be listed in this table. - -![image](images/Introduction_to_Dashboard_Features_5.png) - -#### Top 10 / Bottom 10 Graded Products - -This section summarizes the Graded performance of each Product in your instance, counting the Highest and Lowest scoring Products. - -![image](images/Introduction_to_Dashboard_Features_6.png) - -Finding Counts of each severity are calculated by the tile, but note that Product Grade is only assigned based on Active Findings, so there may be Inactive Findings counted in this table which do not contribute to the Grade. - -To understand how grades are calculated, see our guide to **[Product Health Grading](/asset_modelling/pro_hierarchy/product_health_grade/)**. - -## Dashboard Configuration - -Superusers can choose which Metrics Charts are displayed on the Dashboard. To do this, select the **Edit Dashboard Configuration** option from the top\-right hand gear menu. - -![image](images/How-To_Edit_Dashboard_Configuration.png) -This will open the **Dashboard Configuration Settings** window. - -### Configuration Settings - -![image](images/How-To_Edit_Dashboard_Configuration_2.png) - -* **Display Graphs** determines whether or not the **Historical Finding Severity** and **Reported Finding Severity** charts are visible. -* **Display Surveys determines whether or not the Unassigned Answered Engagement Questionnaires table is visible.** -* **Display Data Tables determines whether or not the Top 10 / Bottom 10 Graded Products tables are visible.** - -### Reset Dashboard Configuration - -If you would like to reset your Dashboard to a default state, you can do so by selecting **Reset Dashboard Configuration** from the top\-right hand gear menu. - -![image](images/How-To_Edit_Dashboard_Configuration_3.png) - -**Note that this will remove any Custom Dashboard Tiles which have been added to your instance.** - -
diff --git a/docs/content/metrics_reports/dashboards/PRO__custom_dashboards.md b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards.md new file mode 100644 index 00000000000..985cfcd2a29 --- /dev/null +++ b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards.md @@ -0,0 +1,200 @@ +--- +title: "Customizable Dashboards" +description: "Build personalized dashboards in DefectDojo Pro from widgets arranged on a drag-and-drop grid" +draft: false +audience: pro +weight: 10 +slug: custom-dashboards +aliases: + - /en/customize_dojo/dashboards/about_custom_dashboard_tiles + - /metrics_reports/dashboards/about_custom_dashboard_tiles +--- +Note: Customizable Dashboards (layouts, widgets, and the widget catalog) are a DefectDojo Pro feature, currently in beta. Beta features are available to DefectDojo Pro Cloud subscriptions β€” contact DefectDojo support or your customer success advocate to enable it for your instance. + +DefectDojo Pro Customizable Dashboards let each user assemble their own home page out of **widgets** β€” counts, charts, leaderboards, feeds, and notes β€” arranged on a drag-and-drop grid. Instead of a single fixed dashboard for everyone, you build the **layouts** that matter to you: an executive overview, a triage queue, a remediation-velocity board, a scanner-effectiveness view. You can keep layouts private, publish them to your whole team, set one as your default landing page, and clone any layout (yours or a shared template) as a starting point. + +![A DefectDojo Pro customizable dashboard β€” the Default Dashboard layout.](images/pro_dashboard_v2_default.png) + +## How it compares to open source + +Open source DefectDojo has a single, built-in [Main Dashboard](../introduction_dashboard/) with a fixed set of summary cards and charts that a superuser can show or hide. It is the same for every user. + +DefectDojo Pro replaces that fixed page with **per-user customizable dashboards**. You choose which widgets appear, how they are filtered, and where they sit on the grid. You can build any number of named layouts, switch between them, share them with your team, and drive the whole system from the [REST API](../custom-dashboards-api/) or an [LLM](../custom-dashboards-llm/). + +> **πŸ’‘ Tip:** In DefectDojo Pro, **Assets** were formerly called **Products** and **Organizations** were formerly **Product Types**. The UI uses the new wording, but some underlying widget settings still use the legacy names β€” for example, most widgets take a `model` of `finding`, `product`, `engagement`, or `test`. Where this matters, it is called out below. + +## Enabling the beta + +Customizable Dashboards are off by default while in beta. Beta features are enabled per instance for DefectDojo Pro Cloud subscriptions β€” contact DefectDojo support ([support@defectdojo.com](mailto:support@defectdojo.com)) or your customer success advocate to turn on Customizable Dashboards for your instance. + +Once it is enabled, the **🏠 Home** page shows your customizable dashboard and the [Dashboards REST API](../custom-dashboards-api/) becomes available. + +> **πŸ”‘ Important:** While the flag is off, the home page keeps the previous dashboard and every `/api/v2/dashboards/` endpoint returns `403 Dashboard V2 is not enabled.` Enabling the flag does **not** change anyone's data access β€” every widget still respects DefectDojo's role-based access control, so each user only ever sees the Findings, Assets, and other records they are authorized to view. + +## Core concepts + +A customizable dashboard is built from a few simple pieces. + +### Layouts + +A **layout** is one named dashboard: a collection of widgets and their positions on the grid. Each layout belongs to you, and you can have as many as you like β€” for example a "Daily Triage" board and a separate "Exec Overview." A layout stores three things: + +- **widgets** β€” the ordered list of widgets it contains, each with its own type, title, and configuration. +- **layout** β€” where each widget sits and how big it is on the grid. +- **settings** β€” layout-level display options. + +The first time you open Customizable Dashboards, DefectDojo gives you a personal copy of the **Default Dashboard** starter so you are never staring at a blank page. + +### Widgets + +A **widget** is a single panel on the dashboard. Every widget is an instance of a **type** from the catalog (a Count, a Graph, a Top-N leaderboard, and so on), and carries its own **configuration**: which data **model** it reads (`finding`, `product`, `engagement`, or `test`), what **filters** scope it, and type-specific display options like chart type, colors, or grouping. Two widgets of the same type with different filters are completely independent. + +Each widget also has an optional **auto-refresh interval** (off, 30 seconds, 1 minute, 5 minutes, or 15 minutes) and an editable **title**. + +### The widget catalog + +The **catalog** is the fixed menu of widget types the platform supports, grouped into four categories β€” **Numbers**, **Charts**, **Lists & Feeds**, and **Static & Utility**. When you add a widget, you pick its type from the catalog. The catalog is also available over the [API](../custom-dashboards-api/) so scripts and LLMs can discover the available widget types and a known-good starting configuration for each. See [The widget catalog](#the-widget-catalog-1) below for the full list. + +### The grid + +Widgets are placed on a **12-column grid**. In edit mode you drag widgets to move them and drag the bottom-right corner to resize them; the grid compacts upward to fill gaps. Each widget type has sensible minimum and maximum sizes so charts and tables stay legible. + +### Sharing, cloning, and defaults + +- **Default** β€” one of your layouts is your **default**: the one that loads when you open the home page. You can change which layout is your default at any time. +- **Clone** β€” copy any layout (one of yours, or a shared template) into your own space as a fresh, independent starting point. Cloning gives the copy its own widgets, so editing the clone never touches the original. +- **Share** β€” publish one of your layouts to the whole team as a **shared layout**. Other users can see it and clone it, but only a team **Maintainer** can publish, edit, or unshare a shared layout. Sharing a layout shares only its *design* β€” every viewer still sees only the data their own permissions allow. +- **Starter & shared templates** β€” DefectDojo ships a set of curated **shared templates** you can clone as a head start (see [Shared templates](#shared-templates) below). The **Default Dashboard** is the special "starter" template that new users are given automatically. + +## Building a dashboard in the UI + +### The dashboard toolbar + +The toolbar across the top of the home page is where you switch layouts and manage them. It includes a **layout picker** (with badges that mark your default layout and any shared layouts/templates), and buttons to create a **New Layout**, open **Manage Layouts**, **Refresh** all widgets, and toggle **Edit** mode. + +![The dashboard toolbar (highlighted): the layout picker, plus New Layout, Manage Layouts, Refresh, and Edit](images/pro_dashboard_v2_home.png) + +### Step 1: Enter edit mode + +Click **Edit** to unlock the dashboard. The grid becomes draggable and resizable, and an **Add Widget** button appears. Click **Done** when you are finished β€” edit mode also turns off automatically when you switch layouts. + +![A dashboard in edit mode, showing drag and resize handles](images/pro_dashboard_v2_edit_grid.png) + +### Step 2: Add a widget + +In edit mode, click **Add Widget** to open the picker. It has two tabs: + +- **By Type** β€” browse the catalog by category (Numbers, Charts, Lists & Feeds, Static & Utility). Each card shows the widget's name and a short description. Picking one adds it to the grid and opens its configuration dialog. +- **From Catalog** β€” start from a pre-configured widget taken from one of the shared templates (for example, the "Findings by Severity" chart from the Default Dashboard). These come ready-configured, so they drop straight onto the grid. + +![The Add Widget dialog, By Type tab](images/pro_dashboard_v2_add_widget.png) + +### Step 3: Configure the widget + +Each widget opens a configuration dialog tailored to its type. Common settings include: + +- **Title** β€” the heading shown on the widget. +- **Model** β€” which records the widget reads (Finding, Asset, Engagement, or Test), where applicable. +- **Filters** β€” an embedded list-view filter UI that scopes the widget to exactly the records you want (for example, active Critical findings). The filters you pick here are the same ones you would use on that object's list page. +- **Refresh interval** β€” how often the widget reloads on its own. +- **Type-specific options** β€” for example chart type and group-by dimension for a Graph, thresholds for a Gauge, or the metric for a Top-N leaderboard. + +![Configuring a Graph widget](images/pro_dashboard_v2_widget_config.png) + +> **πŸ’‘ Tip:** A widget's data always respects your permissions. If a shared layout includes a "My Work" widget, every viewer sees *their own* assignments and mentions β€” not the layout author's. + +### Step 4: Arrange, then save + +Drag widgets to rearrange them and drag a corner to resize. Use the gear icon on a widget to reconfigure it, and the trash icon to remove it. Position and size changes are saved automatically as you go. Click **Done** to leave edit mode. + +### Managing layouts + +The **Manage Layouts** dialog (the gear button on the toolbar) is the hub for everything layout-level: + +- **Your Layouts** β€” rename, set as default, share/unshare, clone, or delete each layout you own. +- **Create New** β€” start a fresh, empty layout to build from scratch. +- **Shared Templates** β€” browse curated and team-published layouts grouped by category, and click **Use Layout** to clone one into your own space. + +![The Manage Layouts dialog](images/pro_dashboard_v2_manage_layouts.png) + +### Shared templates + +DefectDojo ships four ready-to-use shared templates you can clone as a starting point: + +| Template | Purpose | +|----------|---------| +| **Default Dashboard** | The classic home view β€” 12 at-a-glance counts, severity charts, and top/bottom-graded assets. This is the starter every new user receives automatically. | +| **Priority Layout** | A triage-focused board built around finding priority and risk. | +| **Mitigation Layout** | A remediation-velocity board (closure trends, MTTR/MTTD, aging). | +| **Tool Layout** | A scanner-effectiveness board built around test types and recent scan activity. | + +> **πŸ’‘ Tip:** Cloning a template makes an independent copy. Customize the clone freely β€” you will not affect the template or anyone else who clones it. + +### The empty state + +A brand-new layout with no widgets shows a **"Build Your First Dashboard"** prompt. Click **Add Your First Widget** to jump straight into edit mode and start choosing widgets. + +![The empty-layout state](images/pro_dashboard_v2_empty_state.png) + +## The widget catalog + +Customizable Dashboards ship with the following widget types, organized into four categories. Most widgets read one of four models β€” `finding`, `product` (Assets), `engagement`, or `test` β€” and are scoped by filters you choose. The fully detailed configuration options for each widget are documented in the [API guide](../custom-dashboards-api/). + +### Numbers + +Single-glance metrics β€” counts, KPIs, and gauges. + +| Widget | What it shows | +|--------|---------------| +| **Count** | A single number from a filtered query β€” e.g. "Open Critical Findings" or "Active Engagements." Works with finding / asset / engagement / test. | +| **KPI / Trend** | A headline number plus its change versus the prior period, with an optional sparkline. | +| **Gauge** | A ratio drawn as an arc gauge β€” a "universe" filter as the denominator and a "pass" filter as the numerator. Use for SLA compliance, mitigation rate, or scan coverage, with configurable warning/OK thresholds. | +| **License Usage** | Your account's license-usage status with a per-signal breakdown (database size, weekly finding volume, and so on). *Requires the Maintainer role.* | +| **Scan Coverage** | What fraction of assets were scanned within 30 / 90 / 180 / 365 days, as a multi-window rollup. | + +### Charts + +Time-series and distribution visualizations. + +| Widget | What it shows | +|--------|---------------| +| **Graph** | A general-purpose chart over any model and group-by dimension β€” bar, line, area, pie, or doughnut. E.g. Findings by Severity, Findings by Month. | +| **Sankey** | A flow diagram from a source dimension to a target dimension β€” e.g. Severity β†’ Status. | +| **Sunburst** | A one- or two-level radial breakdown β€” e.g. Severity, then Test Type within each severity. | +| **Risk Matrix** | An EPSS-probability Γ— risk heatmap of findings β€” bottom-left safe, top-right dangerous. | +| **Priority Histogram** | The distribution of finding **priority** scores from the prioritization engine, auto-binned. | +| **Rate by Category** | A per-category ratio (numerator / denominator) β€” e.g. False-Positive Rate by Tool or Mitigation Rate by Asset. | +| **Finding Velocity** | Findings created versus closed over time, showing whether the backlog is growing or shrinking. | +| **MTTR / MTTD** | Mean Time to Remediate and Mean Time to Detect, as paired time-series. | +| **Vulnerability Aging** | Open findings bucketed by age band (0–30d / 30–90d / 90–180d / 180d+), stacked by severity. | +| **Activity Heatmap** | A GitHub-style calendar of daily activity over a rolling window. | +| **Portfolio Treemap** | Nested rectangles for a portfolio rollup (Organization β†’ Asset), sized by count and tinted by severity. | + +### Lists & Feeds + +Ranked lists, feeds, and embedded tables. + +| Widget | What it shows | +|--------|---------------| +| **Top-N Leaderboard** | A ranked list in one of two modes: *aggregate* (top dimension buckets by count, e.g. Top 10 CWEs) or *records* (top individual records by a metric, e.g. Top 10 Assets by Grade). | +| **Embedded Table** | A full list view (Findings, Assets, Engagements, Tests, Risk Acceptances, Organizations, or Test Types) with preset filters and ordering β€” pagination, sorting, and CSV export included. | +| **Recent Activity** | A scrolling feed of the most-recently updated records, clickable through to detail pages. | +| **SLA Burndown** | Findings approaching SLA breach, ranked by days remaining, with countdown badges. | +| **My Work** | Your personal queue β€” assignments, mentions, and pending risk-acceptance reviews. Always scoped to the viewer. | +| **Saved Reports** | One-click access to your saved Report Templates. *Requires the Reporting feature.* | + +### Static & Utility + +Notes, shortcuts, and structure. + +| Widget | What it shows | +|--------|---------------| +| **Favorites** | User-curated quick links to specific pages in the app. | +| **Section Break** | A labeled divider for grouping related widgets under a heading. | +| **Markdown / Notes** | An inline rich-text panel for headers, context notes, or reference links. | +| **Quick Actions** | One-click action buttons that navigate to a chosen page. | + +## Next steps + +- **[Automating Dashboards with the API](../custom-dashboards-api/)** β€” discover the widget catalog, create and update layouts, and render widget data over the REST API, with a complete script. +- **[Building Dashboards with an LLM](../custom-dashboards-llm/)** β€” let an LLM design and build dashboards for you (the dashboards API was built with AI agents in mind). diff --git a/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_api.md b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_api.md new file mode 100644 index 00000000000..addac637aa1 --- /dev/null +++ b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_api.md @@ -0,0 +1,487 @@ +--- +title: "Automating Dashboards with the API" +description: "Discover the widget catalog, create and update dashboard layouts, and render widget data via the DefectDojo Pro REST API" +draft: false +audience: pro +weight: 11 +slug: custom-dashboards-api +--- +Note: The Customizable Dashboards REST API (layouts, widget catalog, and widget data) is a DefectDojo Pro feature, currently in beta. Beta features are available to DefectDojo Pro Cloud subscriptions β€” contact DefectDojo support or your customer success advocate to enable it for your instance. + +The Customizable Dashboards REST API lets you build the same dashboards you assemble by hand in the [Dashboards UI](../custom-dashboards/) β€” entirely from code. You can discover the widget catalog, create and update layouts, set your default, share layouts with your team, and even render a widget's data on demand without re-implementing DefectDojo's filtering. The layouts surface was designed as the primary entry point for AI agents building dashboards, so the request shapes are deliberately introspectable. + +This guide walks the full lifecycle: authenticate, discover the widget vocabulary, create a layout, then verify and render it. + +## Authentication + +Every request authenticates with a personal API token sent in the `Authorization` header using the `Token` prefix (not `Bearer`). + +Get your token from the DefectDojo Pro UI under **User Settings β†’ API v2 Key**. Store it in an environment variable so it never lands in your shell history or a committed script: + +```bash +export DD_IMPORTER_DOJO_API_TOKEN="YOUR_API_TOKEN" +``` + +The base URL for all calls is your instance plus `/api/v2`: + +``` +https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2 +``` + +Required headers: + +| Header | Value | When | +|--------|-------|------| +| `Authorization` | `Token YOUR_API_TOKEN` | Every request | +| `Accept` | `application/json` | Every request | +| `Content-Type` | `application/json` | `POST` / `PATCH` with a JSON body | + +A minimal authenticated request looks like this: + +```bash +curl -s \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_catalog/" +``` + +> **πŸ”‘ Important:** The entire Dashboards API is part of the beta. Until it is enabled for your instance, every endpoint returns `403 Dashboard V2 is not enabled.` β€” see [Enabling the beta](../custom-dashboards/#enabling-the-beta). + +> **⚠️ Security Notice:** Your API token grants full access to your DefectDojo data. Never paste it into a chat, screenshot, ticket, or committed file. Read it from an environment variable, rotate it if it is ever exposed, and scope tokens to service accounts where possible. + +## The dashboards API at a glance + +Three resource groups make up the Dashboards API, all under `/api/v2/dashboards/`. + +| Resource | Path | What it is | Operations | +|----------|------|------------|------------| +| Layouts | `/dashboards/layouts/` | Your saved dashboards (and shared team templates) | `GET` list, `POST` create, `GET {id}/`, `PATCH {id}/`, `DELETE {id}/`, plus `{id}/clone/`, `{id}/set_default/`, `shared/`, `for_current_user/` | +| Widget catalog | `/dashboards/widget_catalog/` | The menu of widget types + a config example for each | `GET` (read-only) | +| Widget data | `/dashboards/widget_data//` | On-demand rendered data for a widget | 21 per-widget actions | + +These endpoints accept Token, Session, or Basic authentication. All per-row authorization and data scoping follow DefectDojo's standard role-based access control β€” sharing a layout never widens what its viewers can see. + +> **πŸ’‘ Tip:** The Vue UI calls an internal mirror of these endpoints under `/api/vue/dashboard_v2/`. Always automate against the stable, customer-facing `/api/v2/dashboards/` paths documented here. + +## Step 1: Discover the vocabulary + +Three things in a widget are easy to get wrong if you guess: the **widget type**, its **group-by dimension** (for charts), and its **filters**. The API gives you a source of truth for each. Fetch them first, then build against what the server actually accepts. + +### The widget catalog + +`GET /dashboards/widget_catalog/` returns every widget type, the category it belongs to, the data endpoint(s) it renders against, and β€” most usefully β€” a minimal known-good `config_example` you can copy as a starting point: + +```bash +curl -s \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_catalog/" +``` + +The response is shaped like this (truncated): + +```json +{ + "categories": [ + {"id": "numbers", "label": "Numbers", "description": "Single-glance metrics β€” counts, KPIs, gauges."}, + {"id": "charts", "label": "Charts", "description": "Time-series and distribution visualisations."}, + {"id": "lists", "label": "Lists & Feeds", "description": "Ranked lists, feeds, and embedded tables."}, + {"id": "static", "label": "Static & Utility", "description": "Notes, shortcuts, and quick actions."} + ], + "widgets": [ + { + "type": "count", + "label": "Count", + "category": "numbers", + "description": "Single number rendered from a filtered queryset...", + "data_endpoints": ["/api/v2/dashboards/widget_data/count/"], + "config_example": { + "model": "finding", + "filters": {"status_any": "Active", "severity": "Critical"}, + "icon": "fas fa-ban", + "color": "danger" + } + }, + { + "type": "graph", + "label": "Graph", + "category": "charts", + "description": "Generic chart over any model + group-by dimension...", + "data_endpoints": ["/api/v2/dashboards/widget_data/aggregate/"], + "config_example": { + "model": "finding", + "filters": {"duplicate": "false"}, + "group_by": "severity", + "aggregation": "count", + "chart_type": "pie", + "time_bucket": null, + "limit": null, + "stacked": false + } + } + ] +} +``` + +Use a widget's `type` as the widget's `type`, and its `config_example` as the starting point for the widget's `config`. The catalog lists 26 widget types across the four categories. + +### Group-by dimensions and record metrics + +The chart and leaderboard widgets restrict what you can group or rank by to a curated allowlist. Discover these per model rather than guessing: + +```bash +# Valid group_by dimensions for the Graph / Sankey / Sunburst / Top-N (aggregate) widgets: +curl -s -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" -H "Accept: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_data/dimensions/?model=finding" + +# Valid metrics for the Top-N widget in "records" mode: +curl -s -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" -H "Accept: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_data/record_metrics/?model=product" +``` + +`dimensions/` returns each dimension's `key` (the value to pass as `group_by`), a human `label`, and a `kind`: + +```json +{ + "model": "finding", + "dimensions": [ + {"key": "severity", "label": "Severity", "kind": "categorical"}, + {"key": "status", "label": "Status", "kind": "banded"}, + {"key": "date", "label": "Discovered Date", "kind": "time"}, + {"key": "test_type", "label": "Test Type", "kind": "categorical"} + ] +} +``` + +The `kind` matters: a `time` dimension (like `date`) requires you to also send a `time_bucket` (`day`/`week`/`month`/`quarter`/`year`); a `categorical` or `banded` dimension does not. The `priority` field is intentionally **not** a group-by dimension (it is a continuous score) β€” use the `risk` dimension for a banded view, or the dedicated **Priority Histogram** widget. + +### Filters + +A widget's `config.filters` use the **same filter shape as the object's list view** β€” the values the list page emits to its URL, not the raw REST query parameters. For example, on findings: `{"status_any": "Active"}`, `{"severity": "Critical"}`, `{"duplicate": "false"}`, `{"date_past_days": 7}`, `{"sla_days_remaining_less_than_equal_to": 7}`; on assets: `{"grade": "A,B,C"}`, `{"last_scanned_past_days": 90}`. The quickest way to learn the right filter for a need is to apply it on the relevant list page in the UI and read it back from the widget config dialog, or to copy the filters from the seeded shared templates. + +> **πŸ”‘ Important:** Unknown filter **keys are silently ignored** β€” a misspelled or non-existent filter does not raise an error, it simply does not apply, leaving the widget showing a wider population than you intended. Invalid *values* for a real filter return `400`. Always [verify what you built](#verify-what-you-built) by reading the layout back. (Filters are validated through the same FilterSet the list view uses, so list values may be passed as arrays for "any-of" matching: `{"severity": ["Critical", "High"]}`.) + +> **πŸ’‘ Tip:** Most widgets take a `model` of `finding`, `product`, `engagement`, or `test` β€” note the legacy `product` (the UI calls these **Assets**). The **Embedded Table** widget is the exception: its `model` uses the newer names `finding`, `asset`, `engagement`, `test`, `risk_acceptance`, `organization`, or `test_type`. + +## Step 2: Create a layout + +A layout is created with a `POST` to `/dashboards/layouts/`. The two fields that carry the dashboard's content are `widgets` and `layout`, and they must agree with each other. + +### The widget object + +Each entry in the `widgets` array has this shape: + +```json +{ + "id": "11111111-1111-4111-8111-111111111111", + "type": "count", + "title": "Active Critical Findings", + "refresh_interval": 0, + "config": { "model": "finding", "filters": {"status_any": "Active", "severity": "Critical"}, "color": "danger", "icon": "fas fa-ban" } +} +``` + +- **`id`** β€” a UUID you generate. It ties the widget to its grid position. +- **`type`** β€” a `type` value from the widget catalog. +- **`title`** β€” the heading shown on the widget (up to 200 characters). +- **`refresh_interval`** β€” auto-refresh seconds; one of `0` (off), `30`, `60`, `300`, or `900`. +- **`config`** β€” the type-specific configuration. Start from the catalog's `config_example` and adjust. Each widget type validates its own config server-side and returns a descriptive `400` if something is wrong. +- **`title_styling`** *(optional)* β€” `{"bold": true, "size": "md"}`, where `size` is `sm`, `md`, or `lg`. + +### The layout (grid) map + +`layout` is a map from each widget's `id` to its position on the 12-column grid: + +```json +{ + "11111111-1111-4111-8111-111111111111": {"x": 0, "y": 0, "w": 3, "h": 2, "min_w": 2, "min_h": 2} +} +``` + +- **`x`, `y`** β€” top-left grid coordinates (0-indexed; `x` ranges 0–11). +- **`w`, `h`** β€” width (in columns) and height (in rows). +- **`min_w`, `min_h`** *(optional, default 1)* and **`max_w`, `max_h`** *(optional)* β€” size bounds. + +> **πŸ”‘ Important:** The `layout` map and the `widgets` list must be consistent: **every widget needs a position, and every position must reference a widget that exists.** A mismatch returns `400`. The lifecycle script below builds both together so their IDs always line up. + +### Create the layout + +```bash +curl -s -X POST \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/layouts/" \ + -d '{ + "name": "Exec Overview (API)", + "widgets": [ + {"id": "11111111-1111-4111-8111-111111111111", "type": "count", "title": "Active Critical Findings", + "refresh_interval": 0, "config": {"model": "finding", "filters": {"status_any": "Active", "severity": "Critical"}, "color": "danger", "icon": "fas fa-ban"}}, + {"id": "22222222-2222-4222-8222-222222222222", "type": "graph", "title": "Findings by Severity", + "refresh_interval": 0, "config": {"model": "finding", "filters": {"duplicate": "false"}, "group_by": "severity", "aggregation": "count", "chart_type": "pie", "time_bucket": null, "limit": null, "stacked": false}} + ], + "layout": { + "11111111-1111-4111-8111-111111111111": {"x": 0, "y": 0, "w": 3, "h": 2, "min_w": 2, "min_h": 2}, + "22222222-2222-4222-8222-222222222222": {"x": 3, "y": 0, "w": 9, "h": 4, "min_w": 3, "min_h": 3} + }, + "settings": {} + }' +``` + +The response echoes the saved layout including its new `id`, plus read-only helper fields (`is_default`, `is_owned`, `is_catalog`, `category`, `icon`, and timestamps). + +### Custom actions + +| Action | Call | What it does | +|--------|------|--------------| +| Set default | `POST /dashboards/layouts/{id}/set_default/` | Makes this layout the one your home page loads. You can only default a layout you own. | +| Clone | `POST /dashboards/layouts/{id}/clone/` (optional body `{"name": "..."}`) | Copies a layout (yours or a shared template) into your space with fresh widget IDs. Defaults to `"Copy of "`. | +| List shared | `GET /dashboards/layouts/shared/` | Lists every shared layout β€” curated templates plus team-published ones. | +| Bootstrap | `GET /dashboards/layouts/for_current_user/` | Returns `{"results": [...your layouts...], "default_id": }`. On a first call, it auto-clones the starter template so you always get at least one layout back. | + +Publishing a shared layout (`"is_shared": true` on create or update) requires the global **Maintainer** role. + +## Step 3: Render widget data (optional) + +You usually do not need to render data yourself β€” the dashboard does that when it displays a widget. But the same `widget_data` endpoints are available directly, which is handy for scripts or chat summaries that want to quote a live number. Send the widget's `config` (or the relevant subset) as the payload. + +**A filtered count** (`POST`): + +```bash +curl -s -X POST \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" -H "Content-Type: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_data/count/" \ + -d '{"model": "finding", "filters": {"status_any": "Active", "severity": "Critical"}}' +# β†’ {"count": 42} +``` + +**A group-by aggregation** (`POST`), the data behind a Graph: + +```bash +curl -s -X POST \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" -H "Content-Type: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_data/aggregate/" \ + -d '{"model": "finding", "filters": {}, "group_by": "severity", "aggregation": "count"}' +``` + +```json +{ + "labels": ["Critical", "High", "Medium", "Low", "Info"], + "series": [{"name": "count", "data": [15, 23, 8, 12, 5]}], + "group_by": "severity", + "group_by_label": "Severity", + "model": "finding", + "model_label": "Findings", + "aggregation": "count", + "time_bucket": null +} +``` + +The full set of `widget_data` actions: + +| Action | Method | Key payload / params | Returns | +|--------|--------|----------------------|---------| +| `count` | POST | `model`, `filters` | `{count}` | +| `aggregate` | POST | `model`, `filters`, `group_by`, `aggregation`, `time_bucket?`, `limit?` | `{labels, series, ...}` | +| `dimensions` | GET | `?model=` | valid group-by dimensions | +| `top_records` | POST | `model`, `filters`, `metric`, `limit?`, `sort?` | `{labels, series, ...}` | +| `record_metrics` | GET | `?model=` | valid records-mode metrics | +| `rate_chart` | POST | `model`, `filters`, `pass_filters`, `group_by`, `limit?`, `sort?`, `min_denominator?`, `metric_label?` | rate / numerator / denominator series | +| `sankey` | POST | `model?`, `filters`, `source_dim`, `target_dim` | `{nodes, links, ...}` | +| `sunburst` | POST | `model?`, `filters`, `hierarchy` (1–2 dims) | `{tree, ...}` | +| `scan_coverage` | POST | `model?`, `filters`, `windows?` | per-window bands | +| `risk_matrix` | POST | `filters`, `x_dim?` | EPSS Γ— risk cells (finding-only) | +| `priority_histogram` | POST | `filters`, `bin_count?` | histogram bins (finding-only) | +| `treemap` | POST | `filters`, `metric?` | nested portfolio tree | +| `heatmap` | POST | `filters`, `date_field?`, `window_days?` | per-day calendar cells | +| `aging` | POST | `filters`, `boundaries?`, `date_field?`, `severity_filter?` | stacked age-band series | +| `mttr_mttd` | POST | `filters`, `time_bucket?`, `window_days?` | paired MTTR/MTTD series | +| `velocity` | POST | `filters`, `time_bucket?`, `window_days?` | created vs closed series | +| `my_work` | GET | `?buckets=`, `?limit=` | your assignments / mentions / pending reviews | +| `sla_burndown` | GET | `?days_threshold=`, `?severity_filter=`, `?limit=`, `?include_overdue=` | findings nearing SLA breach | +| `recent_activity` | GET | `?model=`, `?limit=` | recent records feed | +| `saved_reports` | GET | `?limit=` | saved Report Templates *(requires Reporting)* | +| `usage` | GET | β€” | license-usage breakdown *(requires Maintainer)* | + +## Putting it together: a full lifecycle script + +The script below runs the whole flow using only the Python 3 standard library β€” no `requests`, no third-party packages. It reads the token from `DD_IMPORTER_DOJO_API_TOKEN`, discovers the widget catalog, builds a two-widget layout (with the `widgets` list and `layout` map generated together so their IDs always match), creates it, sets it as the default, reads it back to verify, and writes the created ID to `created.json`. + +Set your instance URL and run it: + +```bash +export DD_IMPORTER_DOJO_API_TOKEN="YOUR_API_TOKEN" +export DD_BASE_URL="https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2" +python3 build_dashboard.py +``` + +```python +#!/usr/bin/env python3 +"""Build a DefectDojo Pro dashboard layout end-to-end using only the stdlib.""" + +import json +import os +import urllib.error +import urllib.request +import uuid + +# --- Configuration ------------------------------------------------------- +BASE_URL = os.environ.get( + "DD_BASE_URL", + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2", +).rstrip("/") +TOKEN = os.environ["DD_IMPORTER_DOJO_API_TOKEN"] # fail loudly if unset + + +def api_request(method, path, body=None): + """Make an authenticated request. Returns parsed JSON.""" + url = f"{BASE_URL}{path}" + data = json.dumps(body).encode("utf-8") if body is not None else None + + request = urllib.request.Request(url, data=data, method=method) + request.add_header("Authorization", f"Token {TOKEN}") + request.add_header("Accept", "application/json") + if data is not None: + request.add_header("Content-Type", "application/json") + + try: + with urllib.request.urlopen(request) as response: + payload = response.read() + except urllib.error.HTTPError as error: + # Surface the server's error body to make debugging easy. + detail = error.read().decode("utf-8", errors="replace") + raise SystemExit(f"{method} {path} failed ({error.code}): {detail}") + + return json.loads(payload) if payload else {} + + +def make_widget(widget_type, title, config, *, x, y, w, h, min_w=2, min_h=2): + """Build a (widget, position) pair sharing a freshly generated UUID.""" + widget_id = str(uuid.uuid4()) + widget = { + "id": widget_id, + "type": widget_type, + "title": title, + "refresh_interval": 0, + "config": config, + } + position = {"x": x, "y": y, "w": w, "h": h, "min_w": min_w, "min_h": min_h} + return widget_id, widget, position + + +def main(): + created = {} + + # 1. Discover the catalog so we build against real widget types. + # (We don't strictly need the response here, but fetching it first + # is the recommended pattern β€” copy a config_example as a starting + # point instead of guessing the config shape.) + catalog = api_request("GET", "/dashboards/widget_catalog/") + known_types = {w["type"] for w in catalog["widgets"]} + for required in ("count", "graph"): + if required not in known_types: + raise SystemExit(f"Widget type {required!r} not in catalog.") + print(f"Discovered {len(known_types)} widget types.") + + # 2. Build two widgets and their grid positions together. + widgets = [] + layout = {} + + _id, widget, pos = make_widget( + "count", + "Active Critical Findings", + { + "model": "finding", + "filters": {"status_any": "Active", "severity": "Critical"}, + "color": "danger", + "icon": "fas fa-ban", + }, + x=0, y=0, w=3, h=2, + ) + widgets.append(widget) + layout[_id] = pos + + _id, widget, pos = make_widget( + "graph", + "Findings by Severity", + { + "model": "finding", + "filters": {"duplicate": "false"}, + "group_by": "severity", + "aggregation": "count", + "chart_type": "pie", + "time_bucket": None, + "limit": None, + "stacked": False, + }, + x=3, y=0, w=9, h=4, min_w=3, min_h=3, + ) + widgets.append(widget) + layout[_id] = pos + + # 3. Create the layout. + created_layout = api_request("POST", "/dashboards/layouts/", { + "name": "Exec Overview (API)", + "widgets": widgets, + "layout": layout, + "settings": {}, + }) + layout_id = created_layout["id"] + created["layout_id"] = layout_id + print(f"Created layout id={layout_id} with {len(created_layout['widgets'])} widgets") + + # 4. Make it the default landing dashboard. + api_request("POST", f"/dashboards/layouts/{layout_id}/set_default/") + print(f"Set layout id={layout_id} as the default") + + # 5. Read it back to verify widgets + positions survived intact. + verified = api_request("GET", f"/dashboards/layouts/{layout_id}/") + assert verified["is_default"] is True, "Layout did not become the default" + assert len(verified["widgets"]) == len(widgets), "Widget count mismatch" + assert set(verified["layout"]) == {w["id"] for w in verified["widgets"]}, \ + "Layout map and widgets are out of sync" + print("Verified: default set, widgets and positions consistent") + + # 6. Record the created ID for later cleanup or reuse. + with open("created.json", "w") as handle: + json.dump(created, handle, indent=2) + print("Wrote created.json") + + +if __name__ == "__main__": + main() +``` + +## Verify what you built + +Because invalid filter keys are dropped silently, verification is part of the workflow β€” not an afterthought. + +**Confirm a layout saved as intended.** `GET` it back and check the `widgets` and `layout`: + +```bash +curl -s \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/layouts/12/" +``` + +For each widget, compare the returned `config.filters` to what you sent. If a filter you expected is missing, its key was not a valid filter for that model β€” recheck it against the object's list-view filters. Confirm `is_default` is `true` if you set it, and that every key in `layout` matches a widget `id`. + +**Spot-check a widget's data.** Render its data endpoint and confirm the number is what you expect: + +```bash +curl -s -X POST \ + -H "Authorization: Token ${DD_IMPORTER_DOJO_API_TOKEN}" \ + -H "Accept: application/json" -H "Content-Type: application/json" \ + "https://[YOUR-INSTANCE].cloud.defectdojo.com/api/v2/dashboards/widget_data/count/" \ + -d '{"model": "finding", "filters": {"status_any": "Active", "severity": "Critical"}}' +``` + +**Fix a widget with PATCH.** A `PATCH` to `/dashboards/layouts/{id}/` with the full `widgets` and `layout` replaces them β€” send the complete desired set, not a partial one. + +## Next steps + +- Build and arrange the same layouts interactively in the [Customizable Dashboards UI](../custom-dashboards/). +- Let an LLM design and build dashboards for you with the [Dashboards LLM integration](../custom-dashboards-llm/). diff --git a/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_llm.md b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_llm.md new file mode 100644 index 00000000000..06f72c7f325 --- /dev/null +++ b/docs/content/metrics_reports/dashboards/PRO__custom_dashboards_llm.md @@ -0,0 +1,189 @@ +--- +title: "Building Dashboards with an LLM" +description: "Use Claude or another LLM to design, create, and set up DefectDojo Pro customizable dashboards via the API" +draft: false +audience: pro +weight: 12 +slug: custom-dashboards-llm +--- +Note: Automating Customizable Dashboards with the REST API and an LLM is a DefectDojo Pro feature, currently in beta. Beta features are available to DefectDojo Pro Cloud subscriptions β€” contact DefectDojo support or your customer success advocate to enable it for your instance. + +DefectDojo Pro's Customizable Dashboards are fully driven by the REST API β€” and the layouts surface was designed with AI agents in mind. That means you can hand the whole job to an LLM: paste one self-contained prompt into Claude, ChatGPT, or any other capable model, describe the dashboards you want, and it will interrogate your tenant's live widget catalog, propose layouts, emit a runnable Python script, create the layouts, verify them, and optionally set your default. + +The pattern is simple. You provide your base URL, an API token, and a short description of who the dashboards are for. The LLM does the discovery, design, creation, and verification β€” pausing for your approval before it builds anything against your tenant. + +This guide pairs with the [Dashboards API guide](../custom-dashboards-api/), which documents the raw resources and request shapes the LLM is working with. If you want to understand or hand-tune what the LLM produced, keep that reference open. + +## Before you start + +1. **Get an API token.** In the DefectDojo Pro UI, go to **User Settings β†’ API v2 Key** and copy the token. Then set it as an environment variable so the generated script can read it without the token ever appearing in chat: + +```shell +export DD_IMPORTER_DOJO_API_TOKEN= +``` + +2. **Confirm the beta is enabled.** Customizable Dashboards must be enabled for your instance β€” contact DefectDojo support or your customer success advocate β€” otherwise every API call returns `403`. + +3. **Decide your dashboards.** The LLM will ask what you want. Common choices: + + - **Executive Overview** β€” headline counts, severity distribution, and SLA compliance at a glance. + - **Daily Triage** β€” active criticals/highs, priority histogram, SLA burndown, and your "My Work" queue. + - **Remediation Velocity** β€” created-vs-closed velocity, MTTR/MTTD, and aging. + - **Scanner Effectiveness** β€” findings by test type, false-positive rate by tool, and recent scan activity. + - **Portfolio Health** β€” a treemap of assets by organization, scan coverage, and top/bottom-graded assets. + +> **πŸ’‘ Tip:** You do not have to pick from this list. Tell the LLM your real goals in plain language and it will map them onto the available widget types and filters. + +## The prompt + +Copy the entire fenced block below and paste it into Claude, ChatGPT, or any other capable LLM. The prompt is self-contained β€” the model will ask you for your tenant URL, token environment variable, and dashboard goals, then walk you through discovery β†’ design β†’ create β†’ verify. + +```text +You are helping me build customizable dashboards in DefectDojo Pro using its +REST API ("Dashboards V2" β€” layouts of widgets on a grid). Work carefully and +pause for my approval before creating anything against my tenant. + +================================================================================ +WHAT I WILL GIVE YOU +================================================================================ + - A base URL ending in /api/v2 (e.g. https://my-instance.cloud.defectdojo.com/api/v2) + - The name of an environment variable holding my API token (default: + DD_IMPORTER_DOJO_API_TOKEN). NEVER ask me to paste the token itself. + - A description of the dashboard(s) I want and who they are for. + +Authenticate every request with the header: Authorization: Token +Also send Accept: application/json (and Content-Type: application/json on writes). + +================================================================================ +DATA MODEL +================================================================================ +A "layout" is one dashboard: a named set of widgets and their grid positions. +It is created/updated under /api/v2/dashboards/ with these resources: + + /api/v2/dashboards/layouts/ CRUD for layouts + actions: + POST {id}/clone/ copy a layout (fresh widget IDs) + POST {id}/set_default/ make a layout my home-page default + GET shared/ list curated + team-shared templates + GET for_current_user/ my layouts + my default_id (bootstrap) + /api/v2/dashboards/widget_catalog/ GET: every widget type + a config example + /api/v2/dashboards/widget_data// render a widget's data on demand + +A layout's two content fields MUST agree with each other: + widgets : ordered list of widget objects (see below) + layout : map of widget-id -> {x, y, w, h, min_w?, min_h?, max_w?, max_h?} +Every widget needs a position, and every position must reference a real widget, +or the create returns 400. + +A widget object: + { + "id": "", + "type": "", + "title": "", + "refresh_interval": 0, # one of 0, 30, 60, 300, 900 (seconds) + "config": { ...type-specific... } + } +Optional: "title_styling": {"bold": true, "size": "md"} # size: sm | md | lg + +The grid is 12 columns wide. x is 0..11; w is the column span; y/h are rows. + +================================================================================ +STEP 1 β€” DISCOVER (do this BEFORE designing anything; never invent values) +================================================================================ +1. GET /api/v2/dashboards/widget_catalog/ . It returns {categories, widgets}. + Each widget entry has: type, label, category, description, data_endpoints, + and a minimal known-good config_example. USE THESE config_examples as the + starting point for each widget's config β€” do not guess the config shape. + There are 26 widget types in four categories: Numbers, Charts, + Lists & Feeds, Static & Utility. + +2. For any chart/leaderboard that groups data, fetch the valid dimensions: + GET /api/v2/dashboards/widget_data/dimensions/?model= + Each dimension has key, label, and kind (categorical | boolean | time | + banded). Pass the key as the widget's group_by. A "time" dimension also + needs a time_bucket (day|week|month|quarter|year); others do not. + NOTE: "priority" is NOT a group-by dimension (it is a continuous score). + Use the "risk" dimension for a banded view, or the priority_histogram widget. + +3. For the Top-N widget in "records" mode, fetch valid metrics: + GET /api/v2/dashboards/widget_data/record_metrics/?model= + +================================================================================ +MODELS AND FILTERS (the most error-prone area β€” READ CAREFULLY) +================================================================================ +MODEL: most widgets take a config "model" of EXACTLY one of: + finding | product | engagement | test + (Note the legacy "product" β€” the UI calls these "Assets", and + "engagement"/"test" are unchanged.) Some widgets are finding-only and take + no model (risk_matrix, priority_histogram). The EMBEDDED TABLE widget is the + exception: its model uses the newer names and a wider set: + finding | asset | engagement | test | risk_acceptance | organization | test_type + +FILTERS: a widget's config.filters use the SAME shape the object's LIST VIEW + emits β€” not raw REST query params. Examples that work: + finding: {"status_any": "Active"} # Active | Mitigated | Risk Accepted | ... + {"severity": "Critical"} # single value (or a list for any-of) + {"duplicate": "false"} # boolean as a string + {"date_past_days": 7} + {"sla_days_remaining_less_than_equal_to": 7} + asset: {"grade": "A,B,C"} # passing; "D,F" = failing + {"last_scanned_past_days": 90} + An UNKNOWN filter key is SILENTLY IGNORED (no error) β€” so a typo leaves the + widget showing a wider population than intended. An invalid VALUE for a real + filter returns 400. Because of the silent-drop behavior, you MUST verify + (Step 4). If unsure of a filter name, prefer the values shown in the catalog + config_examples, or ask me to read the filter off the relevant list page. + +================================================================================ +STEP 2 β€” DESIGN, THEN GET MY APPROVAL +================================================================================ +Propose, for each dashboard I asked for: a layout name, and a list of widgets +with their type, title, config, and a sensible 12-column grid arrangement +(x/y/w/h). Show me this plan and the exact JSON you intend to POST. Do NOT +create anything yet. Wait for my explicit "go". + +================================================================================ +STEP 3 β€” CREATE +================================================================================ +After approval, emit a single Python 3 script using ONLY the standard library +(json, os, urllib, uuid β€” no requests). It must: + - read the token from the env var, + - generate a uuid4 per widget and build the widgets list and layout map + together so their IDs always match, + - POST each layout to /api/v2/dashboards/layouts/ and surface any error body, + - optionally POST {id}/set_default/ for the one I choose as my landing page, + - print the created layout IDs. + +================================================================================ +STEP 4 β€” VERIFY +================================================================================ +For each created layout, GET /api/v2/dashboards/layouts/{id}/ and check: + - every key in "layout" matches a widget "id" (and vice versa), + - each widget's config.filters contains what we sent (flag any dropped keys), + - is_default is true for the one I chose. +Report what you verified, and offer to PATCH fixes (a PATCH replaces the full +widgets + layout, so always send the complete set). + +================================================================================ +NOW START +================================================================================ +Ask me for: (1) my base URL, (2) the token env-var name (default +DD_IMPORTER_DOJO_API_TOKEN), and (3) the dashboards I want and their audience. +Then begin at Step 1. +``` + +## What to expect + +A well-behaved model will: + +1. Ask for your base URL, token environment variable, and dashboard goals. +2. `GET` the widget catalog (and dimensions/record-metrics as needed) and tell you which widget types it plans to use. +3. Propose each layout β€” name, widgets, filters, and grid arrangement β€” and **wait for your approval**. +4. Emit a stdlib-only Python script that creates the layouts, optionally sets your default, and verifies the result. +5. Report what it verified and offer to fix anything that did not save as intended. + +> **πŸ’‘ Tip:** If a widget renders an unexpected number, the usual cause is a filter key that was silently dropped. Ask the LLM to read the layout back and compare the saved `config.filters` to what it sent β€” the [API guide](../custom-dashboards-api/#verify-what-you-built) covers this verification step in detail. + +## Next steps + +- See the [Dashboards API guide](../custom-dashboards-api/) for the raw resources, request shapes, and the full widget-data action reference. +- Build and arrange dashboards by hand in the [Customizable Dashboards UI](../custom-dashboards/). diff --git a/docs/content/metrics_reports/dashboards/_index.md b/docs/content/metrics_reports/dashboards/_index.md index d46ef3261a9..a24b41a2d52 100644 --- a/docs/content/metrics_reports/dashboards/_index.md +++ b/docs/content/metrics_reports/dashboards/_index.md @@ -11,6 +11,32 @@ seo: description: "" # custom description (recommended) canonical: "" # custom canonical URL (optional) robots: "" # custom robot tags (optional) -pro-feature: true exclude_search: true ---- \ No newline at end of file +--- +The Dashboard is the front page of DefectDojo β€” a summary of your team's performance and a launchpad for monitoring the areas that matter to you. + +## Open source vs. DefectDojo Pro + +How the dashboard works depends on which edition you run: + +| | Open Source | DefectDojo Pro | +|---|---|---| +| **Home dashboard** | One fixed Main Dashboard for everyone | Per-user **customizable** dashboards | +| **Choose what appears** | Superuser toggles a fixed set of charts on/off | Each user adds, configures, and arranges **widgets** | +| **Multiple named dashboards** | No | Yes β€” build and switch between any number of **layouts** | +| **Share / clone / set a default** | β€” | Yes β€” publish layouts to your team, clone templates, set your default | +| **REST API + LLM automation** | β€” | Yes β€” discover the catalog, create layouts, render widget data | + +In short: **open source** gives every user the same built-in Main Dashboard with a fixed set of components. **DefectDojo Pro** lets each user build their own dashboards out of widgets, share them, and drive the whole system from the UI, the REST API, or an LLM. + +## Where to go next + +**Open Source** + +- **[DefectDojo Main Dashboard](introduction_dashboard/)** β€” the built-in front page: summary cards, severity charts, and how a superuser configures them. + +**DefectDojo Pro** + +- **[Customizable Dashboards](custom-dashboards/)** β€” concepts (layouts, widgets, the catalog, sharing) and a full UI walkthrough. +- **[Automating Dashboards with the API](custom-dashboards-api/)** β€” discover the widget catalog, create and update layouts, and render widget data over the REST API, with a complete script. +- **[Building Dashboards with an LLM](custom-dashboards-llm/)** β€” let an LLM design and build dashboards for you. diff --git a/docs/content/metrics_reports/dashboards/about_custom_dashboard_tiles.md b/docs/content/metrics_reports/dashboards/about_custom_dashboard_tiles.md deleted file mode 100644 index 25b83cf103f..00000000000 --- a/docs/content/metrics_reports/dashboards/about_custom_dashboard_tiles.md +++ /dev/null @@ -1,338 +0,0 @@ ---- -title: "Custom Dashboard Tiles" -description: "How to make Dashboard Tiles work for you, with examples" -weight: 2 -audience: pro -aliases: - - /en/customize_dojo/dashboards/about_custom_dashboard_tiles ---- -Dashboard Tiles are customizable sets of filters for your DefectDojo instance, which can be added to your 🏠 **Home** dashboard. Tiles are designed to provide relevant information and speed up navigation within DefectDojo. - -![image](images/About_Custom_Dashboard_Tiles.png) - -Tiles can: - -* Act as shortcuts for particular sets of Findings, Products, or other objects -* Visualize relevant metrics related a Product, Engagement or other components of the [Product Hierarchy](/asset_modelling/os_hierarchy/product_hierarchy/) -* Provide alerts on particular activity, track SLA Violations, failing imports or new Critical Findings - -Tile Filters set a narrower focus for any tile you want to create. Each Tile has a different set of relevant filters which can be selected. - -Note that only Superusers can add or edit Dashboard Tiles. - -## Tile Components - -Each Tile contains four main components: - -![image](images/About_Custom_Dashboard_Tiles_2.png) - -2. **A count of each object** that meets the Tile’s filter conditions. For example, a Findings Tile will count the number of Findings filtered by the Tile. -3. **A customizable Header** which can be set to describe the function of the tile. -4. **A customizable Footer** which brings you to the related list of objects. For example, a Findings Tile’s footer will bring you to a list of Findings filtered by the Tile. - -## Add / Edit Dashboard Tiles - -Custom Dashboard Tiles can be added, edited or deleted by any user with **Superuser** Permissions. - -New Dashboard tiles can be added by opening the **+** (plus icon) menu on the Dashboard. New Dashboard tiles will always be created at the bottom of the Dashboard Tiles section. - -![image](images/How-To_Add,_Edit_or_Delete_Dashboard_Tiles.png) - -Select the kind of Tile you want to add, which will then bring you to the Add Dashboard Tile form. - -If you wish to **edit** a Dashboard Tile, you can click the Header of the Tile, which will also open the Dashboard Tile form. - -### Display Options - -From here you can set your Dashboard Tile’s options: - -![image](images/How-To_Add,_Edit_or_Delete_Dashboard_Tiles_2.png) - -* Set the **Header** text for your tile **(3)** -* Set the **Footer** text for your tile **(4)** -* Set the **Color** of your icon **(1)** - -![image](images/How-To_Add,_Edit_or_Delete_Dashboard_Tiles_3.png) - -### Tile Filters -Click the **Tile Filters \+** button at the bottom of the form to expand the Tile Filters menu. From here you can apply any relevant filtering to the tile. See the [Tile Index](./#dashboard-tile-index) for more info on what filters can be applied to which tile. - -### Dynamic Color Tile - -If you want to set your tile to change color based on the associated count of Findings, Products or other objects returned by the filter, you can enable **Dynamic Color Tile** in this menu. The color of the tile Icon will change from Green \-\> Yellow \-\> Red as the object count changes. - -* **Dynamic Color Minimum is the bottom of the range. If the Object count is equal to or less than this number, the tile Icon will be set to Green.** -* **Dynamic Color Maximum** is the top of the range. If the Object count is equal to or greater than this number, the tile Icon will be set to Red. -* Any number between the Minimum or the Maximum will set the filter to Yellow. - -#### **Example: Critical Findings Count** - -Say you wanted to set up a Dynamic Color Tile to track our Critical Findings. You can set your Dynamic Color parameters as follows: - -* Set **Dynamic Color Minimum** to 0\. As long as you have 0 active Critical Findings, this tile will be **Green**. -* Set **Dynamic Color Maximum** to 5\. If you have 5 or more Critical Findings active in our environment, the tile will turn **Red** to indicate there’s timely action required to address these Findings. -* If you have 1\-4 Critical Findings in your instance, the filter will be **Yellow** to indicate that we’re not in an β€˜emergency’ situation but we should be aware of these Findings. - -Of course, your team’s standards and acceptable range for this kind of filter may differ from our example. - -#### Inverted Maximum and Minimum - -If your Maximum is lower than your Minimum, the range will still compute correctly. - -**Example 2: Passing Products Count** - -Say you wanted to set up a Tile which tracks your Passing Products with a Dynamic Color. An acceptable count of Passing Products for you is 5 or more, and a β€˜failing’ state is 2 or fewer Passing Products. - -You can set your **Dynamic Color Maximum** of 2, and a **Dynamic Color Minimum** of 5, the Tile will apply colors as follows: - -* If the filter returns 2 Objects or fewer , the tile will be **Red**, indicating that very few of your Products are passing. -* If the filter returns 5 Objects or greater, the tile will be **Green**, indicating that a healthy amount of your Products are passing. -* If the filter returns a value between those two numbers, the tile will be **Yellow**, indicating that a significant, but non\-critical amount of your Products are not passing. - -## Dashboard Tile Index - -Here is a list summarizing each Dashboard Tile you can add, along with filters that can be applied to the Tile and an example configuration. - -### Product, Engagement or Test Tiles - -These Tiles allow you to quickly select a list of Products, Engagements or Tests based on the filter parameters you set. You can use this tile for ease in navigation. - -![image](images/About_Custom_Dashboard_Tiles_3.png) - -The number on the tile represents the count of objects (Products, Engagement or Tests) contained within the tile’s filter parameters. Clicking the footer will take you to a filtered list of those objects. - -#### Example: Monitoring Engagements In Progress - -If you want to create a list of your In\-Progress Engagements in DefectDojo, you can set up an Engagement tile which filters for that condition. - -* Create an Engagement tile, and from the Tile Filters set **Engagement Status** to **In Progress**. -* To make sure your Tile is accurately labeled, set the Header of your tile to β€˜**Engagements In Progress**’. - -![image](images/About_Custom_Dashboard_Tiles_4.png) - -You could also create Engagement tiles for one or more other states, such as **Blocked** or **Completed**. - -#### Product Tile Filters - -* **Product Name Contains**: type in one or more partial matches of Product Names, separated by commas -* **Product Name Exact**: type in one or more exact matches of Product Names, separated by commas -* **Product Type:** Select one or more options from the list -* **Business Criticality**: Select one or more options from the list -* **Platform**: Select one or more options from the list -* **Lifecycle:** Select one or more options from the list -* **Origin:** Select one or more options from the list -* **External Audience:** Yes/No -* **Internet Accessible:** Yes/No -* **Has Tags**: Yes/No -* **Tags:** type in one or more exact matches of tags, separated by commas -* **Tag Contains:** type in one or more partial matches of tags, separated by commas -* **Outside of SLA**: Yes/No - -#### Engagement Tile Filters - -* **Product Name Contains**: type in one or more partial matches of Product Names, separated by commas -* **Product Type**: Select one or more options from the list -* **Engagement Name Contains**: type in one or more partial matches of Engagements, separated by commas -* **Engagement Lead**: Select a single option from the list -* **Engagement Version**: type in an Engagement Version -* **Test Version**: type in a Test Version -* **Product Lifecycle**: Select one or more options from the list -* **Engagement Status**: Select one or more options from the list -* **Has Tags**: Yes/No -* **Tags:** type in one or more exact matches of tags, separated by commas -* **Tag Contains:** type in one or more partial matches of tags, separated by commas -* **Does Not Have Tags**: type in one or more exact matches tags to ignore, separated by commas -* **Tag Does Not Contain**: type in one or more partial matches of tags to ignore, separated by commas - -#### Test Tile Filters - -* **Test Name Contains**: type in one or more partial matches of Test Names, separated by commas -* **Test Type**: select a single Test Type from the list -* **Engagement**: select a single Engagement from the list -* **Test Version:** type in a Test Version -* **Branch/Tag**: type in a Branch/Tag -* **Build ID**: type in a Build ID -* **Commit Hash**: type in a Commit Hash -* **Engagement Tag Contains: type in one or more partial matches of tags, separated by commas** -* **Engagement Tag Does Not Contain**: type in one or more partial matches of tags to ignore, separated by commas -* **Product Tag Contains**: type in one or more partial matches of tags, separated by commas -* **Product Tag Does Not Contain**: type in one or more partial matches of tags to ignore, separated by commas -* **Has Tags**: Yes/No -* **Tags**: type in one or more exact matches of tags, separated by commas -* **Tag Contains**: type in one or more partial matches of tags, separated by commas -* **Does Not Have Tags**: type in one or more exact matches tags to ignore, separated by commas -* **Tag Does Not Contain**: type in one or more partial matches of tags to ignore, separated by commas - -### Finding Tiles - -Finding tiles provide a count of Findings based on the filter parameters you set. As with other tiles, clicking the Footer will take you to a list of the Findings set by the tile. - -![image](images/About_Custom_Dashboard_Tiles_5.png) - -Using filter parameters you can track Findings in a particular state or time period. - -#### Example: Monitoring Critical Findings - -If you wanted to be able to quickly access all of your Critical Findings in DefectDojo, you could do this by creating a tile. - -* Create a Finding tile, and from the Tile Filters set **Severity** to **Critical**. -* To make sure your Tile is accurately labeled, set the Header of the tile to β€˜**Critical Findings**’. - -![image](images/About_Custom_Dashboard_Tiles_6.png) - -You can add additional filter parameters to make this tile more functional for your use\-case. For example, if you wanted this tile to only track Open Findings (and ignore any Mitigated Findings) you could set the **Active** filter to **Yes.** - -#### Finding Tile Filters - -* **Name Contains**: enter a partial match of a Finding Name from the menu -* **Component Name Contains**: enter a partial match of a Component Name from the menu -* **Date**: select an option from the menu -* **CWE**: type in an exact match of a CWE -* **Severity**: select one or more Severities from the menu -* **Last Reviewed**: select an option from the menu -* **Last Status Update**: select an option from the menu -* **Mitigated Date**: select an option from the menu -* **Reported By**: select one or more Users from the menu -* **Product Type**: select one or more Product Types from the menu -* **Product**: select one or more Products from the menu -* **Product Lifecycle**: select one or more Product Lifecycle states from the menu -* **Engagement**: select one or more Engagements from the menu -* **Engagement Version**: type in an exact match of an Engagement Version -* **Test Type**: select one or more Test from the menu -* **Test Version**: type in an exact match of a Test Version -* **Active**: Yes/No -* **Verified**: Yes/No -* **Duplicate**: Yes/No -* **Mitigated**: Yes/No -* **Out Of Scope**: Yes/No -* **False Positive**: Yes/No -* **Has Components**: Yes/No -* **Has Notes**: Yes/No -* **File Path Contains**: type in a partial match of a File Path -* **Unique ID From Tool**: type in an exact match of a Unique ID From Tool -* **Vulnerability ID From Tool**: type in an exact match of a Vulnerability From Tool -* **Vulnerability ID**: type in an exact match of a Vulnerability -* **Service Contains**: type in a partial match of a Service -* **Parameter Contains**: type in a partial match of an Parameter -* **Payload Contains**: type in a partial match of an Payload -* **Risk Accepted**: Yes/No -* **Has Group**: select an option from the list -* **Planned Remediation Date**: select an option from the list -* **Planned Remediation Version**: type in a Planned Remediation Version -* **Reviewers**: select one or more Users from the list -* **Endpoint Host Contains**: type in a partial match of an Endpoint Host -* **Outside of SLA**: Yes/No -* **Effort For Fixing**: select an option from the list -* **Has Tags**: Yes/No -* **Tags**: type in one or more partial matches of Finding tags, separated by commas -* **Tag Contains**: type in one or more partial matches of Finding tags, separated by commas -* **Does Not Have Tags: type in one or more exact matches of Finding tags to ignore, separated by commas** -* **Tag Does Not Contain**: type in one or more partial matches of Finding tags, separated by commas -* **Test Tags**: type in one or more exact matches of tags, separated by commas -* **Test Does Not Have Tags**: type in one or more exact matches of tags to ignore, separated by commas -* **Engagement Tags**: type in one or more exact matches of tags, separated by commas -* **Engagement Does Not Have Tags**: type in one or more exact matches of tags to ignore, separated by commas -* **Product Tags**: type in one or more exact matches of tags, separated by commas -* **Product Does Not Have Tags**: type in one or more exact matches of tags to ignore, separated by commas - -### Endpoint Tiles - -If you need to keep track of particular Endpoints, you can set up a Tile to quickly navigate to a filtered list. This tile can be set up to filter by Host, Product, Tags or other parameters that are relevant to the Endpoints you want to track. - -![image](images/About_Custom_Dashboard_Tiles_7.png) - -Clicking the footer on this tile brings us to a filtered list of Endpoints which displays their status. DefectDojo will only create and track Endpoints with related vulnerabilities, so this will not include any Endpoints which have no vulnerabilities reported. - -#### Example: Monitor All Endpoints With Same Host - -If you wanted to use Endpoints to look at vulnerabilities on a certain part of your architecture, regardless of the associated Product, you could use an Endpoint Tile to filter for a particular URL. From there, you could see all Findings associated with that part of your network. - -* Create an Endpoint tile. For this example, we are setting the Host Contains field to **β€˜centralaction\-items’**, as that string is part of many Endpoint URLs in our infrastructure.​ -* Set your Header to a title which describes the intended function of your tile. In this example, we used **β€˜Host: centralaction\-items’**. - -![image](images/About_Custom_Dashboard_Tiles_8.png) - -#### Endpoint Tile Filters -* **Protocol Contains**: type in a partial match of a Protocol from the menu -* **User Info Contains**: type in a partial match of User Info from the menu -* **Host Contains**: type in a partial match of a Host from the menu -* **Port Contains**: type in a partial match of a Port from the menu -* **Path Contains**: type in a partial match of a Path from the menu -* **Query Contains**: type in a partial match of a Query from the menu -* **Fragment Contains**: type in a partial match of a Fragment from the menu -* **Product**: select one or more Products from the menu -* **Has Tags**: Yes/No -* **Tags**: type in one or more exact matches of tags, separated by commas -* **Tag Contains**: type in one or more partial matches of tags, separated by commas -* **Does Not Have Tags**: type in one or more exact matches tags to ignore, separated by commas -* **Tag Does Not Contain**: type in one or more partial matches of tags to ignore, separated by commas - -### SLA Violation Tile - -This Tile counts Findings which are at risk of violating SLA. It can be set to track all Products, or specific Products chosen from a list. - -#### Example: Findings Approaching SLA Violation - -If you want to create a filter for Findings which are within 7 days of SLA expiration, you can set up your filter parameters to track this. When setting the Filter parameters for the SLA Violation tile, set **β€˜Days Before Expiration’** to **7**. Select either All Products, or a list of specific Products. - -Set the Header to describe the filter you’re applying, for example β€˜SLA Violation \- 3 Days Or Less’. - -![image](images/About_Custom_Dashboard_Tiles_9.png) - -Clicking on the footer will bring you to a list of these Findings for you to address. This tile only tracks Active Findings, but will also track Findings with an expired SLA. - -#### SLA Violation Tile Filters -* **Days Before Expiration**: select an option from the menu -* **Include All Products**: Yes/No -* **Included Products**: select one or more Products from the menu - -### Scan Time Violation Tile - -This Tile is used to track specific Products to ensure that new scan data is being added on a regular basis. - -If there are particular Products which you’re scanning on a regular interval, you can use this tile to ensure your tools and imports are running as expected. - -This Tile will return a count and related list of Products which have **not** had new scan data added in the interval you’ve defined. - -#### Example: Automation Tracking - -If you have scanning tools set to run on a weekly basis, you can use this tile to make sure those automated processes are working correctly. - -* From the Tile filters, select the target Products where the scan data will be imported via automation. Set the Days Since Last Scan field to β€˜Past Week’. -* Set a descriptive name in the Header which communicates the interval you’re testing. - -![image](images/About_Custom_Dashboard_Tiles_10.png) - -If you have multiple scanning intervals that you want to monitor, you can set up multiple tiles to track each one. - -#### Scan Time Violation Tile Filters -* **Days Since Last Scan**: select an option from the menu -* **Include All Products**: Yes/No -* **Included Products**: select one or more Products from the menu - -### Product Grade Tile - -This Tile compares the Product Grade of all Products on your instance, so that you can track any Products which do not meet your grading standard. - -This tile uses a comparison operator (\<, \=, \<\=, \>\=) to track Products which equal, exceed or fail to meet the Product Grade which you want to monitor. - -![image](images/About_Custom_Dashboard_Tiles_11.png) -For more information on how Product Grades are calculated, see our article on [Product Health Grading](/asset_modelling/pro_hierarchy/product_health_grade/). - -#### Example: Track Failing Products - -If you want to quickly access Products in your instance which do not meet your Grading standard, you can set up a Tile which handles that calculation. The Grading standard used in this example is β€˜Less Than C’: we want our tile to flag any Products with a Grade of D or lower. - -* Create a Product Grade Tile. From the Filters list, set the Grade which you consider β€˜failing’. In this case we’ll select C. -* In the Filters list, set a **Comparison Operator** to determine the logic used in counting your failing Products. In this case, we’ll select **β€˜Less Than’**. - -![image](images/About_Custom_Dashboard_Tiles_12.png) - -As with other Product related Tiles, you can set the Tile to look at All Products in your instance, or only a specific list of Products. - -#### Product Grade Tile Filters - -* **Product Grade**: select a single Product Grade from the menu -* **Comparison Operator**: select a Comparison Operator from the menu, related to Product Grade -* **Include All Products**: Yes/No -* **Included Products**: select one or more Products from the menu diff --git a/docs/content/navigation/PRO__filter_index.md b/docs/content/navigation/PRO__filter_index.md index 92f9b44c7ac..234f556cac2 100644 --- a/docs/content/navigation/PRO__filter_index.md +++ b/docs/content/navigation/PRO__filter_index.md @@ -7,7 +7,7 @@ aliases: --- **Note: Currently this article only covers Finding Filters available in the DefectDojo Pro UI, but this article will be expanded in the future to govern more object types, along with Open-Source filters.** -Here is a list of filters that can be applied in the DefectDojo Pro UI to sort lists of Findings. DefectDojo Filters can be used to assist with navigating through lists of Objects, creating custom [Dashboard Tiles](/metrics_reports/dashboards/about_custom_dashboard_tiles/), or creating automation via [Rules Engine](/automation/rules_engine/about). +Here is a list of filters that can be applied in the DefectDojo Pro UI to sort lists of Findings. DefectDojo Filters can be used to assist with navigating through lists of Objects, building custom [dashboards](/metrics_reports/dashboards/custom-dashboards/), or creating automation via [Rules Engine](/automation/rules_engine/about). ## Findings These fields are specific to DefectDojo Findings and are used to organize a Finding. Each of these filters is a separate column in the All Findings table.