Architecture
CHAD is designed as a modern, scalable detection platform. This page explains the key architectural decisions and how components interact.
System Overview
Core Components
Frontend (React)
The frontend is a single-page application built with:
- React 19 with TypeScript for type safety
- React Router for client-side routing
- React Query for server state management
- Tailwind CSS + shadcn/ui for styling
- Monaco Editor for YAML editing with Sigma schema support
Key design decisions:
- All routes are protected - no public pages except login
- Optimistic UI updates with React Query
- WebSocket connection for live alert feed
- Dark mode support throughout
Backend (FastAPI)
The backend is an async Python application:
- FastAPI for high-performance async API
- SQLAlchemy 2.0 with async support for database access
- pySigma for Sigma rule parsing and translation
- APScheduler for background tasks (health checks, SigmaHQ sync)
The backend handles:
- Authentication and authorization (JWT + RBAC)
- Rule validation and translation to OpenSearch queries
- Alert processing and enrichment
- Integration with external services
Database (PostgreSQL)
PostgreSQL stores all configuration and metadata:
- Users and permissions - accounts, roles, API keys
- Rules and versions - Sigma YAML, deployment state, history
- Alert metadata - status, comments, enrichment results
- Configuration - OpenSearch connection, integrations, settings
- Audit logs - complete action history
OpenSearch
OpenSearch handles the detection workload:
- Percolator indices - Store compiled detection queries
- Alert indices - Store alert documents with full log context
- Audit indices - Optional audit log storage for search
Detection Flow
Rule Deployment
When you deploy a rule, CHAD:
- Load the Sigma rule from PostgreSQL
- Translate to OpenSearch query using pySigma with your ECS field mappings
- Create percolator document in
chad-percolator-{index} index
- Update status to deployed in PostgreSQL
Alert Generation
Logs flow to both CHAD and OpenSearch. CHAD performs real-time detection:
- Fluentd sends log to CHAD’s HTTP endpoint (
POST /api/logs/{index_suffix})
- CHAD authenticates request using index pattern’s auth token
- IP allowlist checked (if configured on index pattern)
- Rate limits applied (if enabled)
- CHAD performs percolate query against OpenSearch percolator index
- Matching rules identified from percolator response
- Exception rules checked - if matched, alert suppressed
- GeoIP enrichment applied to configured fields
- TI enrichment - IOCs extracted and looked up
- Alert stored in OpenSearch with deterministic deduplication ID
- WebSocket broadcast for real-time UI updates
- Notifications sent via webhooks, Jira, etc.
Fluentd should be configured with two outputs: one to CHAD for detection, one to OpenSearch for log storage and search.
Data Model
Rules
rules
├── id (UUID)
├── title
├── yaml_content (Sigma YAML)
├── severity (informational, low, medium, high, critical)
├── status (deployed, undeployed, snoozed)
├── threshold_enabled
├── threshold_count
├── threshold_window_minutes
├── tags (MITRE ATT&CK, etc.)
├── created_at, updated_at
└── version_number
rule_versions
├── rule_id (FK)
├── version_number
├── yaml_content (snapshot)
├── changed_by
└── created_at
Alerts
alerts (PostgreSQL - metadata only)
├── id (UUID)
├── rule_id (FK)
├── opensearch_id (reference)
├── status (new, acknowledged, resolved, false_positive)
├── severity
└── created_at
chad-alerts-{index} (OpenSearch - full data)
├── alert_id
├── rule_id, rule_title
├── matched_log (full document)
├── enrichment (TI results)
├── timestamp
└── severity
Exception Rules
rule_exceptions
├── id (UUID)
├── rule_id (FK)
├── field_name
├── operator (equals, contains, regex, in_list, etc.)
├── value
├── group_id (for AND grouping)
└── enabled
Exception logic:
- Conditions with same
group_id are ANDed
- Different groups are ORed
- If any group fully matches, alert is suppressed
Security Architecture
Authentication
- JWT tokens with 8-hour expiration
- Token versioning - password change invalidates all tokens
- Optional TOTP 2FA with backup codes
- SSO support via OIDC/SAML
Authorization (RBAC)
| Role | Permissions |
|---|
| Admin | Full access - users, settings, rules, alerts |
| Analyst | Rules, alerts, exceptions - no user management |
| Viewer | Read-only access to rules and alerts |
Data Protection
- Credentials encrypted with Fernet (symmetric encryption)
- Passwords hashed with bcrypt
- CSRF protection for state-changing operations
- Security headers (HSTS, CSP, X-Frame-Options)
Scalability Considerations
Current Design (Single Instance)
CHAD is currently designed for single-instance deployment:
- Single FastAPI process with async workers
- Background tasks via APScheduler
- PostgreSQL for all state
This handles:
- Thousands of rules
- Millions of alerts
- Small to medium security teams
Future: Horizontal Scaling
For larger deployments, the architecture supports:
- Multiple API instances behind load balancer
- Celery + Redis for distributed background tasks
- Read replicas for PostgreSQL
- OpenSearch cluster for alert storage
Integration Points
Inbound
| Integration | Purpose |
|---|
| OpenSearch | Detection engine, alert storage |
| PostgreSQL | Configuration, metadata |
| SigmaHQ | Rule repository |
Outbound
| Integration | Purpose |
|---|
| Webhooks | Alert notifications (Slack, Discord, custom) |
| Jira Cloud | Automatic ticket creation |
| Threat Intel APIs | IOC enrichment |
Next Steps