<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: implementing-purple-team-metrics-dashboard
description: >-
  Build and maintain purple team metrics dashboards that track detection coverage,
  MTTD, MTTR, exercise outcomes, and security control effectiveness over time.
  Covers metric definitions, data collection from SIEM and ticketing systems,
  Grafana/Kibana dashboard creation, and executive reporting automation.
domain: cybersecurity
subdomain: purple-team
tags:
  - metrics
  - dashboard
  - mttd
  - mttr
  - detection-coverage
  - grafana
  - reporting
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: []
---

# Implementing Purple Team Metrics Dashboard

## Overview

Metrics dashboards translate purple team exercise data into actionable trends and
executive-ready reporting. Tracking detection coverage percentage, mean time to
detect (MTTD), mean time to respond (MTTR), and control bypass rates over time
demonstrates security posture improvement and justifies continued investment.

## Prerequisites

| Requirement | Install |
|---|---|
| Grafana | `docker run -d -p 3000:3000 grafana/grafana-oss` |
| Prometheus | `docker run -d -p 9090:9090 prom/prometheus` |
| Python 3.10+ | For agent tooling and data collection |
| InfluxDB (optional) | For time-series metric storage |
| curl / jq | For API interactions |

## Key Concepts

### Core Metrics

| Metric | Definition | Target |
|---|---|---|
| Detection Coverage | % of tested ATT&CK techniques detected | > 80% |
| MTTD | Mean time from execution to first alert | < 5 min |
| MTTR | Mean time from alert to containment | < 1 hour |
| False Positive Rate | % of alerts that are false positives | < 10% |
| Control Bypass Rate | % of bypass tests that succeeded | < 20% |
| Rule Deployment Lag | Time from rule creation to production | < 48 hours |
| Exercise Frequency | Purple team exercises per quarter | ≥ 4 |

### Metric Data Model

```yaml
purple_team_metrics:
  timestamp: "2026-01-15T10:00:00Z"
  exercise_id: "PT-2026-Q1-001"
  metrics:
    detection_coverage:
      total_techniques: 25
      detected: 20
      percentage: 80.0
    mttd:
      average_seconds: 180
      p50_seconds: 120
      p95_seconds: 600
    mttr:
      average_seconds: 2400
      p50_seconds: 1800
      p95_seconds: 7200
    false_positive_rate:
      total_alerts: 500
      true_positives: 450
      false_positives: 50
      rate: 10.0
    control_effectiveness:
      controls_tested: 12
      bypassed: 2
      bypass_rate: 16.7
```

### Grafana Dashboard JSON

```json
{
  "dashboard": {
    "title": "Purple Team Metrics",
    "panels": [
      {
        "title": "Detection Coverage Trend",
        "type": "timeseries",
        "targets": [
          {
            "expr": "purple_team_detection_coverage_pct",
            "legendFormat": "Coverage %"
          }
        ]
      },
      {
        "title": "MTTD (seconds)",
        "type": "gauge",
        "targets": [
          {
            "expr": "purple_team_mttd_avg_seconds",
            "legendFormat": "Avg MTTD"
          }
        ],
        "fieldConfig": {
          "defaults": {
            "thresholds": {
              "steps": [
                {"color": "green", "value": 0},
                {"color": "yellow", "value": 300},
                {"color": "red", "value": 900}
              ]
            }
          }
        }
      }
    ]
  }
}
```

### Prometheus Metrics Format

```python
# Expose metrics for Prometheus scraping
from prometheus_client import Gauge, start_http_server

detection_coverage = Gauge(
    'purple_team_detection_coverage_pct',
    'Percentage of ATT&CK techniques detected'
)
mttd_avg = Gauge(
    'purple_team_mttd_avg_seconds',
    'Average mean time to detect in seconds'
)
mttr_avg = Gauge(
    'purple_team_mttr_avg_seconds',
    'Average mean time to respond in seconds'
)
bypass_rate = Gauge(
    'purple_team_control_bypass_rate_pct',
    'Percentage of controls bypassed'
)
```

## Workflow

### 1. Collect Metrics from Exercises

```bash
# Aggregate metrics from exercise results
node agent.js collect-metrics \
  --exercise-results results/ \
  --siem-url https://splunk:8089 \
  --output metrics/q1_2026.json
```

### 2. Push to Metrics Store

```bash
# Push metrics to Prometheus pushgateway
node agent.js push-metrics \
  --metrics metrics/q1_2026.json \
  --prometheus-url http://localhost:9091

# Or push to InfluxDB
node agent.js push-metrics \
  --metrics metrics/q1_2026.json \
  --influxdb-url http://localhost:8086 \
  --bucket purple-team
```

### 3. Deploy Dashboard

```bash
# Deploy Grafana dashboard
node agent.js deploy-dashboard \
  --grafana-url http://localhost:3000 \
  --api-key "${GRAFANA_API_KEY}" \
  --template dashboards/purple_team.json
```

### 4. Generate Executive Report

```bash
# Create executive summary from metrics
node agent.js executive-report \
  --metrics metrics/q1_2026.json \
  --output reports/q1_2026_executive.json
```

### 5. Track Trends

```bash
# Compare metrics across quarters
node agent.js trend-analysis \
  --metrics metrics/q4_2025.json metrics/q1_2026.json \
  --output reports/trend_q4_q1.json
```

## Verification

| Check | Method |
|---|---|
| Metrics collected | All exercise data aggregated |
| Dashboard live | Grafana dashboard accessible and populated |
| Trends visible | Multi-period data shows improvement trajectory |
| Executive report generated | Summary includes key metrics and recommendations |

## References

- [Grafana Dashboards](https://grafana.com/docs/grafana/latest/dashboards/)
- [Prometheus Metrics](https://prometheus.io/docs/concepts/metric_types/)
- [MITRE ATT&CK Coverage](https://mitre-attack.github.io/attack-navigator/)
