How to Build Your Own OT Threat Intelligence Dashboard with Open-Source Tools

How to Build Your Own OT Threat Intelligence Dashboard with Open-Source Tools

Hey, OT defender. Tired of sifting through a dozen threat-intel feeds, Excel spreadsheets, and PDF reports just to figure out what’s relevant to your industrial network? Yeah, me too. That’s why I built my own OT-focused threat intelligence dashboard-and you can too.

I’m Zoroasta (🐟), and today I’m giving you the step-by-step guide to building a dashboard that actually shows you the threats that matter to your OT environment. No six-figure SIEM license required. Just open-source tools, a weekend of tinkering, and a healthy dose of trout-level stubbornness.

Why Bother Building Your Own Dashboard?

  1. Customization. Generic dashboards are like oversized suits-they cover the basics but don’t fit your specific OT assets.
  2. Cost. Commercial OT threat-intel platforms can cost more than your annual coffee budget. Open-source is free (minus your time).
  3. Learning. Building it yourself forces you to understand the data, the pipelines, and the detection logic. That knowledge is priceless during an incident.
  4. Control. You own the data, the pipeline, and the output. No vendor lock-in, no surprise license renewals.
  5. The Architecture (Keep It Simple)

    We’ll build a pipeline that:

  6. Collects OT-relevant threat intelligence from open-source feeds.
  7. Enriches that data with context (asset mapping, CVSS scores, etc.).
  8. Correlates it with your internal asset inventory.
  9. Visualizes it in a dashboard that highlights what you need to know.
  10. Here’s the tech stack:

    • Feed ingestion: Python scripts + RSS/CSV/JSON parsers.
    • Data store: PostgreSQL (or SQLite for lightweight).
    • Enrichment: VirusTotal API (free tier), Shodan API (free credits), CVE databases.
    • Correlation: Simple Python matching against your asset list.
    • Dashboard: Grafana (free, gorgeous, flexible).
    • Alerting: Telegram bot or email notifications.
    • Step 1: Gather Your OT-Specific Feeds

      Start with these free, OT-focused intelligence sources:

      | Feed | Format | What it gives you |
      |——|——–|——————-|
      | CISA ICS Advisories | RSS/JSON | CVEs affecting ICS/OT products |
      | ICS-CERT Alerts | RSS | Vulnerability and incident alerts |
      | Dragos OT Threat Intelligence (public blog) | RSS | Threat-actor analysis, campaigns |
      | MITRE ATT&CK for ICS | GitHub repo | TTPs mapped to OT threats |
      | Shodan (search results) | API | Exposed ICS devices, services |
      | Twitter lists (follow @CISAgov, @ICS\_CERT, @DragosInc) | API | Real-time updates, chatter |

      Pro tip: Don’t overload yourself. Start with CISA ICS advisories and Shodan. Add more as you get comfortable.

      Step 2: Set Up the Data Pipeline

      We’ll use Python because it’s the duct tape of cybersecurity. Create a script that:

    • Fetches feed data (using `feedparser` for RSS, `requests` for APIs).
    • Parses and extracts key fields (CVE ID, description, affected vendors, CVSS score).
    • Stores in a PostgreSQL table.
    • Example table schema:

      “`sql
      CREATE TABLE ot_threat_intel (
      id SERIAL PRIMARY KEY,
      source VARCHAR(100),
      title TEXT,
      description TEXT,
      cve_id VARCHAR(20),
      affected_vendors TEXT[],
      cvss_score FLOAT,
      publication_date TIMESTAMP,
      raw_data JSONB,
      ingested_at TIMESTAMP DEFAULT NOW()
      );
      “`

      Step 3: Enrich with Context

      Raw CVEs are boring. Enrich them to answer “So what?” for your environment.

    • VirusTotal API: Check if any IOCs (IPs, domains, hashes) are known malicious.
    • Shodan API: See how many of your external IPs are running the vulnerable service.
    • CVE Details: Use the `cve-search` project (open-source) to get EPSS scores, exploitability, and more.
    • Example enrichment function:

      “`python
      def enrich_with_shodan(cve):
      # Search Shodan for vulnerable service
      results = shodan.search(f’product:”{cve.affected_product}”‘)
      return {
      ‘exposed_count’: results[‘total’],
      ‘top_ports’: [result[‘port’] for result in results[‘matches’][:5]]
      }
      “`

      Step 4: Correlate with Your Asset Inventory

      This is where the magic happens. Create a simple asset inventory (CSV is fine) with:

    • Asset name
    • IP address
    • Vendor (Siemens, Rockwell, Schneider, etc.)
    • Product/version
    • Criticality (High/Medium/Low)
    • Then, match incoming threats against this list:

      “`python
      def match_threat_to_assets(threat, assets):
      matches = []
      for asset in assets:
      if threat[‘affected_vendor’] in asset[‘vendor’]:
      matches.append(asset)
      return matches
      “`

      Now you know which of your assets are affected by a new CVE.

      Step 5: Build the Grafana Dashboard

      Grafana is your best friend here. Install it (Docker makes it easy), connect to your PostgreSQL database, and create panels for:

    • Threat Feed Overview: Bar chart of threats by source (CISA, Dragos, etc.).
    • CVE Severity Breakdown: Pie chart of CVSS scores (Critical, High, Medium).
    • Affected Assets: Table showing which of your assets are impacted by recent CVEs.
    • Exposure Over Time: Line graph of new OT vulnerabilities per week.
    • Top Affected Vendors: Bar chart of Siemens vs. Rockwell vs. Schneider, etc.
    • Make it pretty: Use color coding (red for critical, orange for high). Add drill-down links to the CISA advisory.

      Step 6: Set Up Alerting

      You don’t want to stare at the dashboard all day. Set up alerts for:

    • New CVE with CVSS ≥ 9.0 that affects your vendor.
    • Shodan detection of a vulnerable service on your external IP.
    • CISA advisory mentioning a product you use.
    • Use Grafana’s alerting (to Slack, Telegram, email) or write a simple Python script that sends a Telegram message.

      Step 7: Operationalize It

    • Schedule your feed-ingestion script to run hourly (cron job).
    • Version-control your code (GitHub, GitLab).
    • Document the setup for your team.
    • Test with a tabletop exercise: “A critical CVE drops-how does our dashboard help?”
    • Example Dashboard in Action

      Imagine this scenario:

    • CISA publishes ICS advisory for a Siemens SIMATIC vulnerability (CVSS 9.8).
    • Your script ingests it within the hour.
    • Enrichment finds 500 exposed devices on Shodan.
    • Correlation matches against your asset inventory-you have 12 Siemens PLCs.
    • Dashboard lights up with a red alert.
    • Telegram bot sends you: “🚨 Critical CVE affects Siemens SIMATIC. 12 internal assets impacted. 500 devices exposed worldwide. Take action.”
    • You now have context, priority, and direction-in minutes, not days.

      Common Pitfalls (And How to Avoid Them)

    • Too many feeds. Start with 2-3. Add more only when you’re comfortable.
    • Ignoring false positives. Not every CVE is exploitable in your environment. Tune your correlation logic.
    • Forgetting maintenance. Update your asset inventory regularly. Out-of-date inventory = useless dashboard.
    • No response plan. The dashboard is useless if you don’t act on the alerts. Create playbooks for critical alerts.
    • The Open-Source Tools You’ll Need

    • Python 3.x + `pip install requests feedparser psycopg2 python-shodan`
    • PostgreSQL (or SQLite for small setups)
    • Grafana (docker run -name grafana -p 3000:3000 grafana/grafana)
    • cve-search (optional but helpful)
    • Telegram Bot API (for alerts)

Your Weekend Project Plan

Friday evening: Set up PostgreSQL and Grafana. Write the feed-ingestion script for CISA ICS advisories.

Saturday morning: Add enrichment (Shodan, CVSS). Create asset inventory CSV.

Saturday afternoon: Build Grafana dashboard panels.

Saturday evening: Set up alerting (Telegram bot).

Sunday: Test with real data. Document everything. Pat yourself on the back.

The Bottom Line

Building your own OT threat intelligence dashboard isn’t just a technical exercise-it’s a mindset shift. You move from passive consumer of threat intel to active analyst, correlating global threats with your specific environment.

It’s also a hell of a lot cheaper than buying a commercial platform, and you’ll learn more in one weekend than in a year of vendor demos.

Start small, iterate, and soon you’ll have a dashboard that actually helps you protect your OT network. And when the next big OT vulnerability drops, you’ll be ready-not scrambling.

Zoroasta (trout) – Vice President, Cyborama OT Intelligence. Your OT OSINT sidekick who believes the best tools are the ones you build yourself. 🐟

P.S. Want the starter code? Email me at jeffgray@cyborama.com with “OT Dashboard Code” and I’ll send you the Python scripts and Grafana JSON.

Scroll to Top