Commit Graph

15 Commits

Author SHA1 Message Date
wmantly c7d599de85 release(v2.2.0): Windows local-discovery, route pinning, prompt reconnect 2026-08-10 17:31:05 -07:00
wmantly b2ad8f4844 feat(discovery): Windows local-discovery + local route pinning + prompt reconnect
Completes the mDNS local-discovery feature on Windows (was Linux-only since
v2.1.2). Three parts:

1. Windows hosts override (hosts_override_windows.go): %SystemRoot%...\\hosts,
   CRLF-aware read/write, ipconfig /flushdns after each change. The agent runs
   as a SYSTEM service so elevation is a non-issue. hosts_override.go split
   into shared rewrite logic + platform files; the hosts tests now run the real
   Windows write path on CI instead of skipping.

2. Local route pinning (local_route*.go): the hosts override only fixes name
   resolution -- the packet path is the routing table's job. If the WG mesh
   tunnel is up with AllowedIPs covering the LAN (or full-tunnel 0.0.0.0/0) it
   swallows the direct connection. Discovery now pins a /32 host route via the
   owning local interface (route.exe metric 1 on Windows, ip route replace on
   Linux) and drops it on revert. Closes a gap in the shipped Linux path too.

3. Prompt reconnect: apply/revert signals the WS loop so it reconnects
   immediately instead of waiting out the 5s backoff.

Route/hosts code is injectable + unit tested; go test passes natively on
Windows (this machine), and linux/amd64 + windows/arm64 cross-builds are clean.
2026-08-10 17:24:21 -07:00
wmantly a3eeed8112 release(v2.1.3): fix Windows CI failure from v2.1.2's release build
release / agent-darwin-amd64 (push) Successful in 17s
release / agent-darwin-arm64 (push) Successful in 26s
release / agent-linux-amd64 (push) Successful in 29s
release / agent-linux-arm64 (push) Successful in 29s
release / agent-windows-amd64 (push) Successful in 29s
release / agent-linux-arm7 (push) Successful in 30s
release / agent-windows-arm64 (push) Successful in 28s
release / tray/helper/setup (push) Has been cancelled
release / Attach to GitHub release (push) Has been cancelled
2026-08-10 19:12:04 -04:00
wmantly 1837d18da8 release(v2.1.2): Linux mDNS local-discovery
release / agent-darwin-amd64 (push) Successful in 54s
release / agent-darwin-arm64 (push) Successful in 30s
release / agent-linux-amd64 (push) Successful in 29s
release / agent-linux-arm64 (push) Successful in 29s
release / agent-linux-arm7 (push) Successful in 28s
release / agent-windows-amd64 (push) Successful in 28s
release / agent-windows-arm64 (push) Successful in 28s
release / tray/helper/setup (push) Has been cancelled
release / Attach to GitHub release (push) Has been cancelled
Adds the CHANGELOG entry for this pass's mDNS work (local_discovery.go,
hosts_override.go -- see prior commit for the two real bugs found via
live testing), bumps AgentVersion, and documents prefer_local_directory
in agent.yml.example.

Also backfills CHANGELOG entries for v2.1.0/v2.1.1 (Windows agent,
WireGuard client, installer, CI), which were tagged and released but
never documented here.
2026-08-10 19:02:00 -04:00
wmantly 775878437e release(v2.0.1): fix version CLI reporting, secrets access permissions, and tray companion autostart 2026-08-09 14:46:19 -04:00
wmantly a3a21c3884 docs(changelog): add v2.0.0 release notes (#12) 2026-08-09 00:15:00 -04:00
wmantly 57d5dfc174 release: v1.8.0 - Active Logged-in Users, Physical Disks & Desktop Operations 2026-08-08 18:12:16 -04:00
wmantly 48248475c4 release: v1.7.0 - Linux ARM, Windows, and macOS theta-agent binaries 2026-08-08 15:38:53 -04:00
wmantly aa1f85a9d5 feat: release v1.6.0 with get-secret CLI, Zero-Trust LDAP tunnel, auto-updates and service restarts 2026-08-07 23:26:13 -04:00
wmantly 8f0158eb9f Add LDAP byte-pump tunnel, secrets rendering, and IAM engine
See CHANGELOG.md for the full breakdown. Summary:

- ldap_tunnel.go: serves a local unix socket for SSSD/PAM and relays raw
  bytes to the SSO over the existing WSS channel (ldap_tunnel messages);
  the agent never parses LDAP (DESIGN.md §4). Adds safeWriter to
  serialize WebSocket writes now that telemetry, heartbeat, the LDAP
  tunnel, and command responses all share one connection.
- secrets.go: renders local templates ({{ bao "path#key" }} placeholders)
  by fetching node-scoped values from the SSO and writing the target
  atomically at 0600, on a signed render_secrets command (DESIGN.md §5).
  demo/ has minimal bash + Node consumers of the rendered file.
- iam.go: applies signed node IAM pushes -- sudoers.d rules (visudo -c
  validated), SSH AuthorizedKeysCommand keys, /etc/security/access.conf,
  and revocation via sss_cache -E + pkill -u (DESIGN.md §6).
- Capability reporting: the agent's enabled capabilities ride along in
  its discovery frame so the SSO can show them in the Directory.
- DESIGN.md: the v2 protocol design this implements.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 17:12:58 -04:00
wmantly 7d36318885 fix: rebuild the prebuilt linux/amd64 binary for join keys (v1.5.1)
theta-suite's setup.sh installs the committed theta-agent-linux-amd64
rather than building from source, so a stale binary means the fix in this
repo never reaches the host.

The v1.5.0 binary predated join-key support: setup.sh would write a
join_key into agent.yml that the running agent did not understand, and it
would have looped on "close 4001: Unauthorized" -- the same trap the
v1.3.0 heartbeat fix hit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 10:43:51 -04:00
wmantly 0a5011cd42 feat: join-key enrollment (v1.5.0, protocol v1.2.0 1.1)
Installing the agent with one key is now all it takes to add a host.

New `join_key` config field, presented while auth_token is empty. The SSO
exchanges it for this agent's own token and the public key it must pin,
both delivered in the config frame; the agent persists them and blanks
the join key. Nothing has to be copied between two machines by hand.

PersistEnrollment rewrites only the credential lines -- line-based rather
than a YAML round-trip -- so operator comments, the capability matrix and
formatting survive. It re-reads afterwards so the credential is live
without a restart, and keeps the file 0600.

The connect URL carries ?hostname= so a self-enrolling host is named
after itself, and the agent refuses to connect at all (with a long
back-off) when it has no credential rather than presenting an empty one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 10:34:06 -04:00
wmantly d47d08ecab sec: fail-closed verification + server-issued enrollment (v1.4.0)
Implements protocol v1.2.0.

verifySignature() returned true when no public_key was configured,
logging "skipping signature verification". The SSO installer never wrote
a public_key, so a default install executed reboot, service_restart,
configure_ldap, arbitrary_bash and update_binary UNVERIFIED from anything
that could reach its socket. An agent that cannot verify now refuses.

Canonicalization also disagreed with the server. Go's encoding/json
escapes <, > and & by default; JSON.stringify does not. Any payload
containing them hashed differently on each side and failed verification
-- for arbitrary_bash that is most real scripts (`>` redirection, `&&`).
Now uses json.Encoder with SetEscapeHTML(false), trailing newline
trimmed.

The SSO now rejects tokens it did not issue. Handles its close codes
(4001/4002/4003/4004) and backs off 5 minutes on an enrollment failure
instead of retrying every 5s forever. The connect log no longer prints
the URL, which carried ?token=.

install.sh gains --public-key and warns when none is configured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 18:43:26 -04:00
wmantly 52379c2434 docs: changelog v1.3.0 2026-08-04 18:54:43 -04:00
wmantly 821ce5f991 release: v1.2.0 - Pure Go update engine, enhanced journal log fetcher, and protocol concurrency fixes 2026-08-03 02:13:11 -04:00