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>
This commit is contained in:
@@ -5,6 +5,53 @@ All notable changes to the `theta-agent` daemon will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased] - LDAP byte-pump tunnel (DESIGN.md §4)
|
||||
|
||||
The agent now serves a local LDAP socket for SSSD/PAM. It is a **pure byte
|
||||
pump**: it forwards raw LDAP bytes to the SSO over the WSS channel, and the SSO
|
||||
relays them into its real OpenLDAP and pipes the response back. The agent never
|
||||
parses LDAP.
|
||||
|
||||
### Added
|
||||
- **`ldap_tunnel` capability + `ldap_socket` config.** When enabled, the agent
|
||||
binds a unix socket (default `/run/theta/ldap.sock`, root:theta `0660`) and
|
||||
relays bytes bidirectionally as `ldap_tunnel` messages over the existing WSS
|
||||
channel. Point SSSD at it with `ldap_uri = ldapi://%2frun%2ftheta%2fldap.sock`.
|
||||
- **`safeWriter`** — serializes WebSocket writes. Gorilla allows only one
|
||||
concurrent writer, but telemetry, heartbeat, the LDAP tunnel and command
|
||||
responses all write to the same socket; without this, concurrent writes
|
||||
corrupt the stream.
|
||||
- **Offline behavior:** when the WSS is down the agent cannot forward bytes, so
|
||||
it closes local socket connections; SSSD sees a connection failure and falls
|
||||
back to its local cache.
|
||||
|
||||
### Added — secrets engine (DESIGN.md §5)
|
||||
- **`secrets` capability + `secrets` config.** The agent renders local templates
|
||||
that embed OpenBao secrets (`{{ bao "secret/data/nodes/<id>/<name>#<key>" }}`).
|
||||
It parses the placeholders, fetches the values from the SSO (which holds the
|
||||
OpenBao access; the agent never holds a Vault token), renders each target
|
||||
atomically at `0600`, and runs the configured reload. Triggered by a signed
|
||||
`render_secrets` command.
|
||||
|
||||
### Added — capability reporting
|
||||
- **The agent reports its enabled capabilities in its `discovery` frame.** The
|
||||
SSO stores them and the Directory UI shows them as badges on the host's Metrics
|
||||
tab, so an operator can see at a glance what an agent is allowed to do
|
||||
(telemetry, LDAP tunnel, secrets, IAM, reboot, bash, service control).
|
||||
|
||||
### Added — IAM engine (DESIGN.md §6)
|
||||
- **`iam` capability.** The SSO pushes node-scoped identity config as a signed
|
||||
`iam_apply` command; the agent verifies the Ed25519 signature (fail-closed) and
|
||||
applies it locally:
|
||||
- **Sudo rules** — writes `/etc/sudoers.d/theta-iam-<node_id>`, validates with
|
||||
`visudo -c`, atomic swap.
|
||||
- **SSH keys** — stores per-user keys and installs the `AuthorizedKeysCommand`
|
||||
script (`/usr/local/bin/theta-authorized-keys`) that sshd calls per login.
|
||||
- **Access control** — writes `/etc/security/access.conf` with allowed login
|
||||
groups.
|
||||
- **Revocation** — flushes the SSSD cache (`sss_cache -E`) and drops active
|
||||
sessions (`pkill -u`) for revoked users.
|
||||
|
||||
## [v1.5.1] - 2026-08-06
|
||||
|
||||
### Fixed
|
||||
|
||||
Reference in New Issue
Block a user