- CHANGELOG: sprint 5 entry under [Unreleased] (templates CRUD + instantiation + nav + dropdown + decorrelation). Sprint 4 moved to its own [Sprint 4] section. - README: status bump to sprint 5, test counts refreshed (226/121/201). - tasks/lessons.md: 6 sprint-5 lessons captured (spec-reviewer 2-pass before dispatch finally clicked, endpoint path drift caught visually not by spec-review, screenshot script mocks lag path changes, silent URL "improvements" by backend, apply_patch wrong primitive for creation copy paths, IntegrityError catch beats pre-check SELECT, SendMessage rule applies to all team agents). - tasks/todo.md: status flipped to 🟢 SPRINT COMPLET. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
161 lines
6.9 KiB
Markdown
161 lines
6.9 KiB
Markdown
# Mimic
|
|
|
|
**Mimic** is a Breach and Attack Simulation (BAS) web UI built on the MITRE ATT&CK matrix. It replaces the flat Excel spreadsheets that red-teams and SOC analysts pass around at the end of an engagement, providing a shared workspace for Purple Team handoffs.
|
|
|
|
> Status: **Sprint 5 — Simulation templates**. Admin/redteam can now create reusable simulation templates (name + description + commands + prerequisites + MITRE techniques + tactics) and instantiate them inside an engagement in one click. Template and instance are fully decoupled — editing one never affects the other. SOC has no access to templates.
|
|
|
|
---
|
|
|
|
## Quick start
|
|
|
|
Prerequisites: Docker (or Podman) + GNU Make. Linux/macOS host.
|
|
|
|
```bash
|
|
# 1. Configure secrets
|
|
cp .env.example .env
|
|
# Edit .env and set MIMIC_JWT_SECRET to a strong random value:
|
|
# sed -i "s|replace-me-with-a-strong-random-secret|$(openssl rand -hex 32)|" .env
|
|
|
|
# 2. Build and start the container
|
|
make build
|
|
make start
|
|
|
|
# 3. Bootstrap the first admin (run once, the container must be up)
|
|
make create-admin USER=alice PASS=changeme8
|
|
|
|
# 4. Open the UI
|
|
xdg-open http://localhost:5000 # Linux
|
|
# or visit http://localhost:5000 manually
|
|
```
|
|
|
|
Log in with the credentials from step 3. The admin can create additional users (redteam / soc) from `/admin/users`.
|
|
|
|
To stop or restart:
|
|
|
|
```bash
|
|
make stop
|
|
make restart # stop + start, preserves the SQLite volume
|
|
make logs # tail container logs
|
|
```
|
|
|
|
To override the host port:
|
|
|
|
```bash
|
|
make start PORT=8080
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
Single-container deployment. A multistage Dockerfile builds the Vite frontend, then copies the static assets into the Flask backend image so Flask serves both the API (under `/api/*`) and the SPA (everything else).
|
|
|
|
```
|
|
┌───────────────────────────────────────────┐
|
|
│ Container: mimic:latest │
|
|
│ │
|
|
│ Flask (Python 3.12) │
|
|
│ ├── /api/* ── blueprints (auth, users, │
|
|
│ │ engagements, simulations,│
|
|
│ │ mitre) │
|
|
│ └── / ── SPA fallback → React build │
|
|
│ │
|
|
│ SQLAlchemy ── SQLite at /data/mimic.sqlite │
|
|
│ (volume: mimic-data)│
|
|
└───────────────────────────────────────────┘
|
|
```
|
|
|
|
- **Auth**: JWT Bearer tokens (HS256, 60-min TTL). Stateless — no refresh tokens, no server-side session.
|
|
- **Roles**: `admin` (super-user — cumulates redteam rights on engagements/simulations), `redteam` (CRUD engagements + simulations, full field access), `soc` (read everything, write-only on the SOC half of simulations once the redteam marks them `review_required`).
|
|
- **Password hashing**: argon2 via `argon2-cffi`.
|
|
- **Migrations**: Alembic, applied automatically by the container entrypoint (`flask db upgrade && flask run`).
|
|
- **MITRE ATT&CK**: STIX 2.1 Enterprise bundle committed at `backend/data/mitre/enterprise-attack.json` and indexed at app boot. `make update-mitre` re-fetches the latest bundle and (if the container is running) restarts it to reload the index. The endpoint `GET /api/mitre/techniques?q=` powers the autocomplete on simulations.
|
|
- **Simulation workflow**: Pending → In progress (auto-transition when redteam saves any non-empty field) → Review required (manual, redteam) → Done (manual, redteam or SOC). The state machine is enforced server-side; the UI surfaces the appropriate transition button per role + current state.
|
|
|
|
See [`SPEC.md`](SPEC.md) § "Décisions techniques" for the full architecture rationale and [`DESIGN.md`](DESIGN.md) for the UI design system.
|
|
|
|
---
|
|
|
|
## Project layout
|
|
|
|
```
|
|
mimic/
|
|
├── backend/ # Flask app, SQLAlchemy models, Alembic migrations, pytest suite
|
|
├── frontend/ # Vite + React + Tailwind + TanStack Query, Vitest suite
|
|
├── e2e/ # Playwright acceptance tests (one spec per user story)
|
|
├── docker/ # Dockerfile (multistage) + entrypoint.sh
|
|
├── tasks/ # Sprint plans (tasks/todo.md) and lessons (tasks/lessons.md)
|
|
├── .claude/agents/ # Sub-agent definitions for the team (read-only at runtime)
|
|
├── Makefile # all operational entry points
|
|
├── SPEC.md # functional + technical spec
|
|
├── DESIGN.md # UI design system (palette, typography, components)
|
|
└── CHANGELOG.md
|
|
```
|
|
|
|
---
|
|
|
|
## Make targets
|
|
|
|
| Target | What it does |
|
|
|---|---|
|
|
| `make build` | Build the `mimic:latest` container image (multistage: Node → Python). Uses `docker` if installed, otherwise `podman` — override with `make build CONTAINER_CMD=podman` |
|
|
| `make start` | Start the container (port from `PORT`, default 5000; mounts `mimic-data` volume) |
|
|
| `make stop` | Stop and remove the container |
|
|
| `make restart` | `make stop && make start` — preserves the SQLite volume |
|
|
| `make update` | `git pull && make build && make restart` |
|
|
| `make logs` | `docker logs -f mimic` |
|
|
| `make create-admin USER=… PASS=…` | Run `flask create-admin` inside the container |
|
|
| `make update-mitre` | Fetch the latest MITRE STIX 2.1 Enterprise bundle into `backend/data/mitre/`; auto-restart the container if running. Commit the resulting file change manually. |
|
|
| `make test-backend` | `pytest -q` inside the container |
|
|
| `make test-frontend` | `npm run test -- --run` in `frontend/` |
|
|
| `make test-e2e` | Playwright acceptance suite (container must be running) |
|
|
| `make clean` | Remove container + volume + Python/Node caches |
|
|
| `make open-pr TITLE="…" BODY=path` | Open a PR on the Gitea repo for the current branch via the REST API. Reads credentials from `~/.git-credentials` (same source as `git push`) — no token in env. Wraps `scripts/open-pr.sh`. Defaults `BASE=main`. |
|
|
|
|
---
|
|
|
|
## Development (without Docker)
|
|
|
|
Backend:
|
|
|
|
```bash
|
|
cd backend
|
|
python -m venv .venv && source .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
export MIMIC_JWT_SECRET=dev-secret
|
|
export MIMIC_DB_PATH=./mimic.sqlite
|
|
flask --app backend.app:create_app db upgrade
|
|
flask --app backend.app:create_app run --port 5000
|
|
```
|
|
|
|
Frontend:
|
|
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev # http://localhost:5173 with /api proxied to :5000
|
|
```
|
|
|
|
Tests:
|
|
|
|
```bash
|
|
cd backend && pytest -q # 226 tests
|
|
cd frontend && npm run test -- --run # 121 tests
|
|
cd e2e && npx playwright test # 201 tests (needs container up — use MIMIC_BASE_URL=http://127.0.0.1:5000 if localhost resolves to IPv6)
|
|
```
|
|
|
|
---
|
|
|
|
## Documentation
|
|
|
|
- [`SPEC.md`](SPEC.md) — functional spec, technical decisions, agent team
|
|
- [`DESIGN.md`](DESIGN.md) — UI design system
|
|
- [`CHANGELOG.md`](CHANGELOG.md) — sprint-by-sprint changes
|
|
- [`tasks/todo.md`](tasks/todo.md) — current sprint plan
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
Internal project — not yet open-sourced.
|