Skip to content

Latest commit

 

History

History
293 lines (242 loc) · 8.04 KB

File metadata and controls

293 lines (242 loc) · 8.04 KB

PurpleOPS BAS - Architecture

System Overview

┌─────────────────────────────────────────────────────────────┐
│                         PurpleOPS BAS                          │
│                   Purple Team Platform                      │
└─────────────────────────────────────────────────────────────┘

┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│   Frontend   │───▶│   Backend    │───▶│  Postgres    │
│  (ClojureScript) │ │(Clojure/Ring)│    │   Database   │
└──────────────┘    └──────────────┘    └──────────────┘
                           │
                           ▼
                    ┌──────────────┐
                    │ Orchestrator │
                    │ (core.async) │
                    └──────────────┘
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
   ┌─────────┐       ┌─────────┐       ┌─────────┐
   │  Planner│       │Executor │       │ Critic  │
   └─────────┘       └─────────┘       └─────────┘
                                             │
                                             ▼
                                        ┌─────────┐
                                        │Reporter │
                                        └─────────┘

Component Details

Frontend (ClojureScript + Reagent + re-frame)

  • Location: frontend/
  • Tech: ClojureScript, Reagent (React wrapper), re-frame (state management)
  • Build: shadow-cljs
  • Serves: Dashboard, Exercise management, Scenario library, Reports
  • Port: 8080 (Nginx in Docker)

Backend (Clojure + Ring + Reitit)

  • Location: backend/
  • Tech: Clojure, Ring, Reitit, Integrant
  • DB: Postgres via next.jdbc + HikariCP
  • Auth: JWT + RBAC (Buddy)
  • API: RESTful endpoints
  • Port: 3000

Orchestrator (Clojure + core.async)

  • Location: orchestrator/
  • Tech: Clojure, core.async
  • Pipeline: Planner → Executor → Critic → Reporter
  • Port: 3001 (health check)

Planner

  • Loads scenario from DB
  • Validates allowlist and authorization
  • Creates execution plan
  • Safety first: blocks dangerous actions

Executor

  • Executes actions from plan
  • Multimethod dispatch by action type
  • Respects timeouts
  • Logs all actions

Critic

  • Imports detections from connectors
  • Compares expected vs actual
  • Calculates metrics (detection rate, TTD, TTC)
  • Identifies gaps

Reporter

  • Generates final report
  • Persists results to DB
  • Creates recommendations

Database (PostgreSQL)

  • Schema: migrations/
  • Tables: users, exercises, scenarios, runs, detections, evidences, audit_log
  • Indexes: Optimized for queries
  • Migrations: Migratus

Connectors

  • Location: connectors/
  • Purpose: Import telemetry from external tools
  • Types: SIEM, EDR, Logs
  • Formats: JSON, API calls, file imports

Network Architecture

Docker Networks

control-plane (172.20.0.0/24)
├── frontend:80
├── backend:3000
├── postgres:5432
└── orchestrator:3001

lab-net (172.21.0.0/24)
└── (for scenario execution)

Isolation

  • control-plane: Management and API
  • lab-net: Scenario execution (isolated from production)

Security Architecture

Authentication & Authorization

  1. Login: POST /api/auth/login → JWT token
  2. JWT: Signed with HS256, expires in 8h
  3. RBAC: 4 roles (admin, purple-lead, analyst, viewer)
  4. Middleware: wrap-auth, wrap-require-role

Exercise Approval Flow

Create Exercise
     ↓
[pending] → (requires allowlist + proof-of-authorization)
     ↓
Approve (by purple-lead/admin)
     ↓
[approved]
     ↓
Start Execution
     ↓
[running] → Orchestrator processes
     ↓
[completed/failed]

Safety Guardrails

  1. Allowlist Validation: Every target must be in scope
  2. Proof of Authorization: Ticket ID required
  3. Action Blacklist: Blocks dangerous keywords (exploit, malware, etc.)
  4. Production Check: Rejects targets with "prod" in name
  5. Audit Log: All actions logged with user, timestamp, IP

Audit Trail

  • Table: audit_log
  • Captures: user_id, action, details, timestamp, ip_address
  • Middleware: wrap-audit-log (automatic)

Data Flow

Exercise Execution Flow

1. User creates exercise (UI)
   ↓
2. POST /api/exercises (Backend)
   ↓
3. Validation (allowlist, proof-of-auth)
   ↓
4. Saved as [pending] (DB)
   ↓
5. Purple Lead approves (UI)
   ↓
6. POST /api/exercises/:id/approve (Backend)
   ↓
7. Status → [approved] (DB)
   ↓
8. User starts exercise (UI)
   ↓
9. POST /api/exercises/:id/start (Backend)
   ↓
10. Create run record (DB)
    ↓
11. Submit to orchestrator (async)
    ↓
12. Orchestrator pipeline:
    Planner → Executor → Critic → Reporter
    ↓
13. Results saved to DB
    ↓
14. User views report (UI)

Deployment Architecture

Containers (Alpine-based)

Backend:
  Builder (clojure:temurin-21-alpine) → uberjar
  Runtime (eclipse-temurin:21-jre-alpine) → non-root user

Orchestrator:
  Builder (clojure:temurin-21-alpine) → uberjar
  Runtime (eclipse-temurin:21-jre-alpine) → non-root user

Frontend:
  Builder (node:20-alpine) → shadow-cljs build
  Runtime (nginx:alpine) → static files

Hardening

  • Non-root users (1001, 1002)
  • Read-only filesystems (where possible)
  • Minimal capabilities
  • Healthchecks (every 15-30s)
  • Resource limits (CPU, memory)

Configuration

Environment Variables

# Backend
DATABASE_URL=jdbc:postgresql://...
JWT_SECRET=...
ENVIRONMENT=production
LOG_LEVEL=info

# Orchestrator
DATABASE_URL=jdbc:postgresql://...
BACKEND_URL=http://backend:3000

Config File (optional)

  • backend/resources/config.edn
  • Aero-based with profiles (:dev, :production)

Monitoring & Observability

Healthchecks

  • Backend: GET /health
  • Orchestrator: GET /health (port 3001)
  • Frontend: Nginx status

Logs

  • Structured logging (timbre)
  • Volumes: backend-logs, orchestrator-logs
  • View: docker compose logs -f <service>

Metrics (future)

  • Prometheus endpoint: /metrics
  • Grafana dashboard

Scaling Considerations

Horizontal Scaling

  • Backend: Stateless (can scale with load balancer)
  • Orchestrator: Single instance (or use queue for distribution)
  • Database: Read replicas for queries

Performance

  • Connection pooling (HikariCP)
  • Async execution (core.async)
  • Caching (can add Redis)

Development Workflow

# Backend REPL
cd backend && clj -M:dev

# Frontend watch
cd frontend && npm run watch

# Database migrations
clj -M:migratus migrate

# Tests
clj -M:test

Technology Stack Summary

Layer Technology
Frontend ClojureScript, Reagent, re-frame, shadow-cljs
Backend Clojure, Ring, Reitit, Integrant
Orchestrator Clojure, core.async
Database PostgreSQL 16
Auth JWT (Buddy)
Containers Docker, Alpine Linux
Web Server Nginx (frontend), Jetty (backend)
Logging timbre
HTTP Client clj-http
JSON Cheshire

Future Enhancements

  • WebSocket for real-time updates
  • Prometheus metrics export
  • LLM integration for AI agents
  • Plugin system for custom actions
  • API versioning
  • Rate limiting
  • GraphQL API option