3.2 KiB
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.