Files
2026-05-25 10:39:32 +08:00

3.2 KiB

PatchProbe Server

Node.js / Express server that receives scan payloads from enrolled PatchProbe devices and exposes a management API.


First-run setup

1. Configure environment

cp config.example.env .env
# Edit .env — at minimum set PATCHPROBE_ADMIN_KEY_HASH (see below)

2. Generate an admin key

node server.js --gen-admin-key
# Prints a random key and its bcrypt hash.
# Paste the hash into PATCHPROBE_ADMIN_KEY_HASH in .env
# Store the key itself securely — it is only shown once.

3. Start the server

npm start          # production
npm run dev        # development (auto-reload, pretty logs)

On first start the SQLite database is created automatically at DB_PATH (default ./patchprobe.db).


Enrolling a device end-to-end

Step 1 — Create an enrollment token (admin)

curl -X POST http://localhost:3000/api/admin/tokens \
  -H "Authorization: Bearer <admin-key>" \
  -H "Content-Type: application/json" \
  -d '{"label": "lab-devices", "expiresInDays": 7, "maxUses": 10}'
# Response: { "token": "<64-char hex>", ... }
# The token value is only returned here — copy it now.

Step 2 — Enroll the device (on the endpoint)

PatchProbe.exe enroll --server-url http://your-server:3000 --enrollment-key <token>

The client POSTs to POST /api/enrollments, receives a deviceId, and stores credentials encrypted on disk.

Step 3 — Run a scan

PatchProbe.exe scan
# Collects evidence and POSTs signed payload to POST /api/scans

Admin API reference

All /api/admin/* routes require Authorization: Bearer <admin-key>.

Method Path Description
POST /api/admin/tokens Create enrollment token (label, expiresInDays?, maxUses?)
GET /api/admin/tokens List tokens (value masked as ab12****)
DELETE /api/admin/tokens/:token Revoke a token
GET /api/admin/devices List all enrolled devices
DELETE /api/admin/devices/:id Revoke a device (blocks future scan uploads)
GET /api/admin/devices/:id/scans Scan summaries for a device

Device API (used by PatchProbe.exe — do not change)

Method Path Auth
POST /api/enrollments Enrollment token in body
POST /api/scans ECDSA device signature headers
GET /api/scans None
GET /api/scans/:id None
DELETE /api/scans/:id None

Smoke test

# Start server first (auth must be enabled, admin key configured)
node test-auth.js

Architecture notes

  • Persistence: SQLite via Node.js built-in node:sqlite (no native compilation). WAL mode, foreign keys enforced.
  • Device auth: ECDSA-P256-SHA256 over deviceId\ntimestamp\nbase64(sha256(rawBody)). Raw body bytes are captured before JSON parsing so re-serialization cannot alter the signed content.
  • Admin auth: bcrypt-hashed bearer key. bcrypt comparison is async (non-blocking).
  • Enrollment tokens: constant-time comparison iterates all active tokens without early exit to prevent timing oracles.
  • Rate limiting: 10 req/min on /api/enrollments, 60 req/min on /api/scans.