7d36318885
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>
6.3 KiB
6.3 KiB
Changelog
All notable changes to the theta-agent daemon will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[v1.5.1] - 2026-08-06
Fixed
- Rebuilt the prebuilt
theta-agent-linux-amd64. theta-suite'ssetup.shinstalls that committed binary rather than building from source, so a stale one means the fix in this repo never reaches the host. The v1.5.0 binary predated join-key support: an install would have written ajoin_keyintoagent.ymlthat the running agent did not understand, and it would have looped onclose 4001: Unauthorized. (Same trap as the v1.3.0 heartbeat fix.)
[v1.5.0] - 2026-08-06
Join-key enrollment (protocol v1.2.0 §1.1). Installing the agent with one key is now all it takes to add a host.
Added
join_keyconfig field. Presented whileauth_tokenis empty. The SSO exchanges it for this agent's own token and the public key it must pin, both delivered in theconfigframe; the agent writes them intoagent.ymland blanks the join key. No value has to be copied between two machines by hand any more.ConfigManager.PersistEnrollmentrewrites only the credential lines, line-based rather than a YAML round-trip, so operator comments, the capability matrix and formatting survive. Re-reads the file afterwards, so the new credential is live without a restart, and keeps the file at0600.Config.Credential()— the agent's own token when it has one, otherwise the join key.- The connect URL carries
?hostname=, so a self-enrolling host is named after itself instead of a generated placeholder. install.sh --join-key.
Fixed
- The agent now refuses to connect (with a clear message and a long back-off) when it has neither an
auth_tokennor ajoin_key, rather than repeatedly presenting an empty credential.
[v1.4.0] - 2026-08-05
Implements Protocol v1.2.0. See PROTOCOL.md §1.1, §5.1–5.3.
Security
- Fail-closed signature verification.
verifySignaturereturnedtruewhen nopublic_keywas configured, logging "skipping signature verification". Combined with an installer that never wrote apublic_key, that meant a default install would executereboot,service_restart,configure_ldap,arbitrary_bashandupdate_binaryunverified from anything that could reach its socket. An agent that cannot verify a high-risk command now refuses it. - The token must be issued by the server. The SSO now rejects tokens it did not mint (close code
4001). Agents carrying a token generated by the old browser-side installer will not connect until re-enrolled.
Fixed
- Canonicalization mismatch broke signatures for most real scripts. Go's
encoding/jsonescapes<,>and&by default; the server'sJSON.stringifydoes not. Any payload containing them — anarbitrary_bashscript using>redirection or&&, which is most of them — hashed differently on each side and failed verification.canonicalize()now usesjson.EncoderwithSetEscapeHTML(false)and trims the encoder's trailing newline. - Auth failures no longer hot-loop. A rejected credential was retried every 5 seconds forever, flooding the SSO and its audit log. Close codes
4001/4003/4004now back off for 5 minutes and log what to do about it. - The auth token no longer appears in logs. The connect line logged the full URL, including
?token=.... It now logs only host + path, and the token is URL-escaped.
Added
- Close-code handling for the SSO's enrollment signals:
4001unauthorized,4002superseded,4003revoked,4004token rotated. install.sh --public-key <base64>, written into the generatedagent.yml. The installer warns loudly when no public key is configured, since such an agent can report telemetry but will refuse every high-risk command.- Tests: fail-closed with no key, wrong key, payload tampered after signing, shell metacharacters (
>,&&,<) round-tripping, and canonical-form equality with the server.interop_check_test.goverifies a signature produced by the live SSO against the agent's own verifier (skipped unlessINTEROP_FIXTUREis set).
Changed
- Existing tests no longer rely on verification being skipped; high-risk cases now sign with a real test key.
agent.yml.example,README.md,INSTALL.md: enrollment is a prerequisite, andpublic_keyis the base64 of the raw 32-byte Ed25519 key — not a PEM body. The previous documented example (MCowBQYDK2VwAyEA...) decodes to 44 bytes and would have been rejected.
[v1.3.0] - 2026-08-04
Fixed
- Silently ignore
heartbeat_ack— the server replies to the agent's own periodic heartbeat withheartbeat_ack. The agent had no case for it, so it fell through to the unknown-command handler, loggedUnknown command type: heartbeat_ackevery minute, and answered with a spurious error response. Heartbeat acks are fire-and-forget; the agent now ignores them silently.
[v1.2.0] - 2026-08-03
Added
- Protocol v1.1.0 Compliance: Full alignment with
PROTOCOL.md(v1.1.0) specification. - Ed25519 Cryptographic Verification: Verification of Ed25519 Base64 signatures for high-risk C2 commands (
reboot,service_restart,configure_ldap,arbitrary_bash,update_binary). - Enhanced Journal Log Fetcher (
fetch_logs): Support for querying service-specific systemd logs (serviceparameter) with configurable line count (linesparameter). - Pure Go Self-Update Engine (
update_binary): Replaced shell script execution with pure Go HTTP client fetching, SHA256 verification, atomic file replacement, and clean daemon restart.
Fixed
- Goroutine Leak Prevention: Added
stopChlifecycle management to terminate background telemetry and heartbeat tickers upon WebSocket disconnection. - Dynamic Config Rerenders: Resolved data races when toggling capabilities or reloading
agent.ymlviareload_config. - Config Path Uniformity: Standardized canonical configuration file path across codebase, installer, and documentation to
/etc/theta42/agent.yml.
[v0.1.0] - 2026-08-01
Added
- Initial release of
theta-agentGo daemon replacing legacy bash metric scripts. - Persistent outbound WebSocket telemetry and local capability matrix enforcement.