cd80be3b13
migration 0011 adds pending_hosts table (id, hostname, public_key,
fingerprint, expiry). store/pending_hosts.go covers full CRUD plus
hostname-collision count + expired-row sweeper.
POST /api/agents/announce takes {hostname, os, arch, agent_version,
restic_version, public_key (base64)}, returns {pending_id,
fingerprint, hostname_collision}. Per-source-IP token-bucket
rate limit (10/min) + global cap of 100 in-flight rows. Public
key must be exactly 32 bytes (Ed25519).
40 lines
1.7 KiB
SQL
40 lines
1.7 KiB
SQL
-- 0011_pending_hosts.sql
|
|
--
|
|
-- P2-18: announce-and-approve enrolment.
|
|
--
|
|
-- Agents that don't have an enrolment token announce themselves
|
|
-- with `POST /api/agents/announce`, persisting one row here. The
|
|
-- admin sees them in the dashboard's Pending hosts panel and can
|
|
-- accept (mints a real Host row + bearer) or reject (deletes the
|
|
-- row + closes the agent's pending WS).
|
|
--
|
|
-- public_key is the agent's Ed25519 public key (32 raw bytes).
|
|
-- fingerprint = "SHA256:" + hex(sha256(public_key)) — printed by
|
|
-- the install script on the endpoint terminal so the operator can
|
|
-- compare the two before clicking accept. This comparison is the
|
|
-- load-bearing security gate for this flow.
|
|
--
|
|
-- expires_at is set to first_seen_at + 1h on insert; a sweeper
|
|
-- goroutine (P2-18b) deletes rows past their expiry. Hostname
|
|
-- collisions with existing or other pending rows are *not*
|
|
-- prevented at the DB level — multiple announces with the same
|
|
-- hostname are flagged in the UI so admin can pick the right one.
|
|
|
|
CREATE TABLE pending_hosts (
|
|
id TEXT PRIMARY KEY,
|
|
hostname TEXT NOT NULL,
|
|
os TEXT NOT NULL,
|
|
arch TEXT NOT NULL,
|
|
agent_version TEXT NOT NULL,
|
|
restic_version TEXT NOT NULL,
|
|
public_key BLOB NOT NULL, -- 32-byte Ed25519
|
|
fingerprint TEXT NOT NULL, -- "SHA256:hex(...)"
|
|
announced_from_ip TEXT NOT NULL,
|
|
first_seen_at TEXT NOT NULL,
|
|
last_seen_at TEXT NOT NULL,
|
|
expires_at TEXT NOT NULL
|
|
);
|
|
CREATE INDEX pending_hosts_expires ON pending_hosts(expires_at);
|
|
CREATE INDEX pending_hosts_fingerprint ON pending_hosts(fingerprint);
|
|
CREATE INDEX pending_hosts_hostname ON pending_hosts(hostname);
|