first commit
This commit is contained in:
108
README.md
Normal file
108
README.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
cp config.example.env .env
|
||||
# Edit .env — at minimum set PATCHPROBE_ADMIN_KEY_HASH (see below)
|
||||
```
|
||||
|
||||
### 2. Generate an admin key
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user