store+server: P2-18a announce-and-approve schema + endpoint
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).
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
-- 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);
|
||||
Reference in New Issue
Block a user