Files
dashboards/.agents/phases/todo/15_agent_mtls/07_live_rollout.md
T
ducoterra 04d934dd94 chore(agent): phase 15_agent_mtls from TODO.md (protected exporter web servers)
The single TODO item (exporters as protected web servers, certs as auth,
root certificate generated and managed by the collector) is now phase 15:
cert management in meta, agent TLS mode, https collector dials, gated
/api/certs surface, /certs admin page, installer + live rollout.

LLM-Generated: true
2026-10-19 13:25:45 -04:00

3.6 KiB

Task 07 — The fleet runs TLS: install, flip, verify, document

Phase: 15_agent_mtls · Source: TODO.md:3 — "I want all exporters to be protected web servers. The collector should generate and manage a root certificate that needs to be installed with each exporter. Use the certs as auth to each exporter."

Objective

The two live agents (deskwork, gateway) present the dashboard-issued server cert and require the dashboard's client cert; the dashboard dials https://; the health table, the live suite, and a /certs screenshot prove it — and the still-missing driveripper install is documented to carry a bundle from day one.

Work

  1. Fleet (operator root actions, the deploy/agent-sudoers grant): for deskwork and gateway: GET /api/certs/<name>/bundle (a signed-in curl), scp the bundle to the host, sudo ./deploy/install-agent.sh --cert-bundle <file>, systemctl restart dashboards-agent, ./deploy/install-agent.sh --status green over TLS. Record the exact commands + output in data/logs/NOTES-agent-install.md (an append to the file's existing per-host record; local evidence, not tracked, the AGENTS.md rule).
  2. The flip: .env.dev — the HOST_TARGETS entries become https://<same address>:9120 (no userinfo — the cert is the auth; the token goes away for a TLS host), ./scripts/dev-server.sh restart, ./scripts/dev-server.sh status shows host:deskwork ok, host:gateway ok, disks:deskwork ok, disks:gateway ok (the two driveripper jobs stay DOWN — unchanged, the designed degradation).
  3. Proof (invariant 10): uv run pytest -m live --live — the host/disks tests over the https path; a /certs screenshot (the table showing both rows active, issued rev == deployed rev) and a /system screenshot (the host rows not dimmed) in data/logs/; a data/logs/NOTES-verify.md-style note: the curl codes (unsigned /api/certs refused, signed-in 200), one line for a wrong-CA client's handshake failure (the redacted URL only).
  4. The driveripper procedure: an append to data/logs/NOTES-agent-install.md — when the agent is finally installed (the outstanding operator action, the AGENTS.md fleet section), install the bundle in the same invocation (sudo ./deploy/install-agent.sh --bind … --cert-bundle …) and point HOST_TARGETS at https:// from day one; a token-only install after this phase is a host the https-dialing dashboard cannot reach.
  5. Docs (the AGENTS.md definition of done): the AGENTS.md fleet section (the transport fact: the agent is now mTLS, the bundle file, the /certs page) + the commands section (the bundle-fetch line); a short "Protecting the agent" section in README.md (the operator's how-to: fetch the bundle, install, flip the URL — three sentences, no flavour).

Testing & Quality

  • the live suite is read-only (the repo's rule) — no bundle mutations on the hardware; the revocation/rotation proof happens on a dev-box agent, not the fleet's.
  • invariant 10: the dev server stays up throughout; screenshots in data/logs/.

Completion Criteria

  • ./scripts/dev-server.sh status: host:deskwork ok, host:gateway ok, disks:deskwork ok, disks:gateway ok over the https:// dials
  • uv run pytest -m live --live green for the host/disks paths
  • the /certs + /system screenshots in data/logs/ show active, issued rev == deployed rev, the host rows not dimmed
  • the data/logs/ note records the exact commands + the curl codes + the wrong-CA failure line
  • AGENTS.md + README.md updated (the definition of done)
  • bash .agents/validate.sh green