hub v0.159.0 (R-1154, after security review): the enroll reuse path re-issues nothing, it warns the operator
The first draft (5121536f, unpushed) re-issued the claim code and the off-site login on a
reuse whose old box was stale or switched off. A security review flagged it: the caller
holds only the household's retrieval passphrase, and both re-issues are operator
session-only actions (05 section 17.5, 09 decision 252, R-1055/R-1059). Now the reuse
path classifies the old box and re-issues nothing: gone -> host_reinstall_over_old_host
(warning, mailed to the operator: delete the old host and re-run, or re-issue by hand);
live -> host_reenroll_while_live (info). The mint path after the operator's delete is
unchanged and still re-issues. The once-per-silence record and the claim engine comment
edit are reverted. 05 section 8, README and CHANGELOG updated; tests red-proved.
This commit is contained in:
+10
-12
@@ -113,9 +113,9 @@ type Handler struct {
|
||||
poker Poker
|
||||
|
||||
// staleThreshold (R-1154, v0.159.0) is the hub's report-liveness threshold (alerting.stale_threshold — the
|
||||
// same value hostStatus and both staleness checkers read). The host-enroll REUSE path re-issues the
|
||||
// clean-slate credentials only when the old box has been silent past it (reenroll.go). 0 = not wired: the
|
||||
// reuse path then never re-issues (the pre-v0.159.0 behaviour — the fail-safe direction). main wires it.
|
||||
// same value hostStatus and both staleness checkers read). The host-enroll REUSE path judges by it whether
|
||||
// the old box is gone (a reinstall over the old record → the operator's warning mail) or live (reenroll.go).
|
||||
// 0 = not wired: no verdict, a log line only. main wires it.
|
||||
staleThreshold time.Duration
|
||||
}
|
||||
|
||||
@@ -1218,8 +1218,9 @@ func (h *Handler) handleHostEnroll(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Mint-once-reuse: an existing host for this customer is returned as-is (idempotent) — the SAME host id and
|
||||
// key, so re-running the installer never orphans a live agent's key and a reinstalled box takes over the
|
||||
// record. R-1154 (v0.159.0): when the old box has gone silent (or was switched off on purpose), this
|
||||
// enroll is a reinstall and the clean-slate re-issues run here too — reenroll.go decides.
|
||||
// record. The clean-slate re-issues do NOT run here: they are operator session-only powers and the
|
||||
// passphrase must not reach them (R-1154, reenroll.go). A reinstall over the old record is made LOUD — an
|
||||
// operator-only warning mail saying to delete the old host and re-run, or re-issue by hand.
|
||||
existing, err := h.store.GetHostByCustomer(req.CustomerID)
|
||||
if err != nil {
|
||||
h.logger.Printf("[ERROR] host-enroll: host lookup failed for %s: %v", req.CustomerID, err)
|
||||
@@ -1233,7 +1234,7 @@ func (h *Handler) handleHostEnroll(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Internal error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
h.reissueOnReuseIfReinstall(cc, existing, time.Now())
|
||||
h.noteReenrollOverExistingHost(cc, existing, time.Now())
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{"host_id": existing.HostID, "api_key": existing.APIKey})
|
||||
@@ -1260,17 +1261,14 @@ func (h *Handler) handleHostEnroll(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Printf("[INFO] host enrolled: %s (customer %s)", hostID, req.CustomerID)
|
||||
|
||||
// F2 (v0.57.0) — clean-slate reinstall of an existing customer. This mint path fires exactly
|
||||
// once per fresh host record (a host deleted before the reinstall), so it is one of the two
|
||||
// single-shot re-enroll hooks — the other is the reuse path above for a silent old host (R-1154).
|
||||
// For a CLAIMED customer the fresh box has no
|
||||
// once per fresh host record (the operator deleted the stale host, so re-enroll mints), so it is
|
||||
// the single-shot re-enroll hook — and the operator's delete is its gate (R-1154: the reuse path
|
||||
// above never re-issues; it tells the operator to delete). For a CLAIMED customer the fresh box has no
|
||||
// password; auto-issue a reset code so the customer isn't stranded at the claim page hunting for
|
||||
// the manual "request a new code" button (delivery rides the report ACK). No-op for an unclaimed
|
||||
// customer (first provision). Also re-issue offsite credentials to the fresh box (F3) — the
|
||||
// one-time offsite password only ever reached the OLD controller, so the fresh one has no target.
|
||||
h.reissueOnReenroll(cc)
|
||||
// R-1154: the record that the re-issues ran for this host record — an installer --resume that
|
||||
// enrolls again before the new agent's first report must not re-issue a second time.
|
||||
h.recordReenrollReissued(cc.CustomerID, hostID, "a new host record")
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
Reference in New Issue
Block a user