package store import ( "database/sql" "fmt" "net/netip" ) // OperatorOOBNote marks the single fleet-wide operator OOB peer among wg_peers (TASK H1). It is an // UNBOUND peer (host_id ''), so it rides the existing empty-host_id support + the partial-unique // idx_wg_peers_host (which only constrains non-empty host_id) without collision [OF-4]. It is pushed // to the endpoint by peersync like any peer (so the endpoint accepts the operator's handshake), and // its assigned_ip becomes each box's desired-state oob_peer_ip (rendered into wg-felhom AllowedIPs). const OperatorOOBNote = "operator-oob" // GetOperatorOOBPeer returns the fleet operator OOB peer, or (nil, nil) if none is registered. func (s *Store) GetOperatorOOBPeer() (*WGPeer, error) { var p WGPeer err := s.db.QueryRow( `SELECT pubkey, assigned_ip, host_id, note, created_at FROM wg_peers WHERE note = ? LIMIT 1`, OperatorOOBNote). Scan(&p.Pubkey, &p.AssignedIP, &p.HostID, &p.Note, &p.CreatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } return &p, nil } // SetOperatorOOBPeer registers/rotates THE operator OOB peer at an EXPLICIT tunnel address (so the // endpoint's STATIC forward chain can hardcode the operator /32). Last-write-wins: any prior // operator-oob row is replaced (key rotation / IP change). Validated: assignedIP is an IPv4 host // address inside the endpoint's tunnel_subnet, not the network/broadcast/pbs_tunnel_ip, and not // already taken by a DIFFERENT (customer) peer. host_id stays '' (unbound) so it is never counted as // a customer host. func (s *Store) SetOperatorOOBPeer(pubkey, assignedIP string) error { ip, err := netip.ParseAddr(assignedIP) if err != nil || !ip.Is4() { return fmt.Errorf("operator oob: assigned_ip %q is not an IPv4 address", assignedIP) } tx, err := s.db.Begin() if err != nil { return err } defer tx.Rollback() var subnet, pbsIP string err = tx.QueryRow(`SELECT tunnel_subnet, pbs_tunnel_ip FROM wg_endpoints ORDER BY endpoint_id LIMIT 1`). Scan(&subnet, &pbsIP) if err == sql.ErrNoRows { return ErrWGEndpointUnset } if err != nil { return err } pfx, err := netip.ParsePrefix(subnet) if err != nil { return fmt.Errorf("operator oob: endpoint tunnel_subnet %q unparseable: %w", subnet, err) } if !pfx.Contains(ip) { return fmt.Errorf("operator oob: assigned_ip %s is not inside tunnel_subnet %s", assignedIP, subnet) } if ip == pfx.Masked().Addr() || ip.String() == pbsIP || ip == lastAddr(pfx) { return fmt.Errorf("operator oob: assigned_ip %s is a reserved address (network/broadcast/pbs)", assignedIP) } // The IP must be free OR already this operator peer's (idempotent re-set at the same IP). var otherPubkey string err = tx.QueryRow(`SELECT pubkey FROM wg_peers WHERE assigned_ip = ? AND note != ?`, assignedIP, OperatorOOBNote). Scan(&otherPubkey) if err == nil { return fmt.Errorf("operator oob: assigned_ip %s is already taken by peer %s", assignedIP, shortKey(otherPubkey)) } if err != sql.ErrNoRows { return err } // The pubkey must not be bound to a host (an operator peer is never a customer key). var boundHost string err = tx.QueryRow(`SELECT host_id FROM wg_peers WHERE pubkey = ? AND host_id != ''`, pubkey).Scan(&boundHost) if err == nil { return fmt.Errorf("operator oob: pubkey is already bound to host %s — refusing", boundHost) } if err != sql.ErrNoRows { return err } if _, err := tx.Exec(`DELETE FROM wg_peers WHERE note = ?`, OperatorOOBNote); err != nil { return err } if _, err := tx.Exec(`INSERT INTO wg_peers (pubkey, assigned_ip, host_id, note) VALUES (?, ?, '', ?)`, pubkey, assignedIP, OperatorOOBNote); err != nil { return err } return tx.Commit() } // oobOperatorSSHKeyKey is the hub_settings key for the fleet operator SSH public key (H1). const oobOperatorSSHKeyKey = "oob_operator_ssh_pubkey" // SetOOBOperatorSSHKey stores the operator's SSH PUBLIC key (an authorized_keys line, delivered to // every box via the desired-state so felhom-sshd honours the operator login). "" clears it. func (s *Store) SetOOBOperatorSSHKey(pubkey string) error { return s.setSetting(oobOperatorSSHKeyKey, pubkey) } // GetOOBOperatorSSHKey returns the operator SSH public key ("" if unset). func (s *Store) GetOOBOperatorSSHKey() string { return s.getSetting(oobOperatorSSHKeyKey) } func shortKey(k string) string { if len(k) > 12 { return k[:12] + "…" } return k }