8f0158eb9f
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>
125 lines
7.1 KiB
Markdown
125 lines
7.1 KiB
Markdown
# Theta Agent
|
|
|
|
Theta Agent is a unified endpoint management daemon for the theta42 stack. It replaces legacy bash installation scripts and one-way metric scripts with a powerful, 2-way Command & Control (C2) Go daemon.
|
|
|
|
The agent dials out to the central SSO Manager via a persistent WebSocket connection, enabling real-time telemetry, dynamic discovery, and secure remote operations.
|
|
|
|
## What you get
|
|
|
|
Install the agent on a node and it becomes a managed member of the directory — over a **single outbound connection**, with no inbound ports, no LDAP hostname/firewall/TLS setup, and no manual secret copying.
|
|
|
|
- **Directory logins (LDAP byte pump).** SSSD/PAM on the node authenticates through the agent's local socket, which forwards raw LDAP bytes to the SSO's OpenLDAP. OS logins work across any network — laptops, CGNAT, cloud VMs — and fall back to the local SSSD cache when offline.
|
|
- **Secrets delivered automatically.** Services get their config files (DB passwords, TLS keys, API tokens) rendered from OpenBao to disk, atomically, with a post-render reload. Rotate a secret and it propagates.
|
|
- **IAM managed centrally.** Sudo rules, SSH keys, and login access are pushed from the SSO to the node. Add a user to a group and their access appears on the right hosts; revoke them and their sessions are dropped.
|
|
- **Telemetry & remote operations.** Host discovery, live metrics, and signed remote commands (reboot, service control, config, self-update) — the original C2 capabilities.
|
|
|
|
Everything is gated by a strict, local-first capability matrix and high-risk operations are Ed25519-signed (see below).
|
|
|
|
## Core Functionality
|
|
|
|
### 1. Telemetry & Observability
|
|
- **Host Discovery**: Pushes a comprehensive profile (IPs, OS, Kernel, CPU, RAM/Disk) upon connection and automatically updates when network interface IPs change.
|
|
- **Continuous Monitoring**: Streams metrics every 30 seconds:
|
|
- CPU, RAM, and Root Disk usage.
|
|
- **ZFS Health**: Monitors pool status via `zpool list`.
|
|
- **GPU Utilization**: Tracks NVIDIA GPU usage via `nvidia-smi`.
|
|
- **Health Checks**: Sends a periodic heartbeat to the SSO Manager to signal agent viability.
|
|
|
|
### 2. Remote Operations (C2)
|
|
The agent provides a powerful set of administrative tools, categorized by risk:
|
|
|
|
#### Standard Operations
|
|
- **Config Reload**: Triggers a reload of `/etc/theta42/agent.yml` from disk without restarting the process.
|
|
- **Log Streaming**: Fetch the last 100 lines of the agent's system logs via the C2 channel.
|
|
|
|
#### High-Risk Operations (Require Cryptographic Signatures)
|
|
To prevent unauthorized execution, these commands must be signed with a private key corresponding to the `public_key` in `agent.yml`:
|
|
- **Service Control**: Restart approved systemd services.
|
|
- **System Control**: Trigger a full system reboot.
|
|
- **Config Management**: Update `/etc/sssd/sssd.conf` and restart `sssd`.
|
|
- **Remote Execution**: Execute raw bash scripts.
|
|
- **Self-Update**: Securely download, verify (SHA256), and apply a new binary version.
|
|
|
|
## The Security Model (Blast Radius & Zero-Trust)
|
|
|
|
Because Theta Agent runs as `root`, it is a high-value target. To prevent lateral movement and contain the blast radius, it operates on a **strict, local-first capability matrix**.
|
|
|
|
### Local Configuration Wins
|
|
The agent will **only** execute commands that are explicitly enabled in its local configuration file (`/etc/theta42/agent.yml`). The central SSO Manager cannot override these settings.
|
|
|
|
### Cryptographic Hardening
|
|
All high-risk commands require an Ed25519 signature. The agent verifies the signature against the `public_key` provided in the local config. If the signature is missing or invalid, the command is rejected regardless of the capability matrix.
|
|
|
|
Verification is **fail-closed**: an agent with no `public_key` configured rejects
|
|
every high-risk command. (Before protocol v1.2.0 it logged "skipping signature
|
|
verification" and executed them, so an agent installed without a key would run
|
|
`reboot`, `configure_ldap` and `arbitrary_bash` unverified.)
|
|
|
|
### Enrollment
|
|
The agent's token must be **issued by the SSO**. The server stores only its
|
|
SHA-256 and rejects anything else at the WebSocket handshake, so a token cannot
|
|
be minted client-side, and an enrollment can be revoked or rotated centrally —
|
|
either drops the agent's live connection immediately. See `PROTOCOL.md` §1.1.
|
|
|
|
### Capability Matrix
|
|
|
|
| Capability | Risk Level | Description | Impact |
|
|
|------------|------------|-------------|---------|
|
|
| `telemetry` | Safe | Read-only metrics. | Pushes system health to SSO Manager. |
|
|
| `configure_ldap` | Moderate | Configures SSSD. | Updates `/etc/sssd/sssd.conf` and restarts `sssd`. |
|
|
| `ldap_tunnel` | Moderate | Local LDAP byte-pump socket. | Forwards raw LDAP bytes to the SSO for SSSD/PAM (DESIGN.md §4). |
|
|
| `secrets` | Moderate | Renders OpenBao secrets. | Renders `/etc/theta/templates/*.tpl` to targets, atomic + reload (DESIGN.md §5). |
|
|
| `iam` | High | Applies node IAM. | Writes sudo rules, SSH keys, access control; revokes sessions (DESIGN.md §6). |
|
|
| `reboot` | High | System reboot. | Triggers an immediate host reboot. |
|
|
| `service_control` | High | Service management. | Restarts services listed in the allowed list. |
|
|
| `arbitrary_bash` | CRITICAL | Raw bash execution. | Executes any script sent by the manager as root. |
|
|
|
|
## Configuration
|
|
|
|
Configuration is stored in YAML format at `/etc/theta42/agent.yml`.
|
|
|
|
### Example `agent.yml`
|
|
```yaml
|
|
server_url: "wss://sso.theta42.local"
|
|
auth_token: "issued-by-the-sso-at-enrollment"
|
|
public_key: "base64-encoded-ed25519-public-key"
|
|
location: "dc-01-rack-12"
|
|
capabilities:
|
|
telemetry: true
|
|
configure_ldap: true
|
|
reboot: true
|
|
service_control: ["nginx", "gitea", "sssd"]
|
|
arbitrary_bash: false
|
|
```
|
|
|
|
## Installation
|
|
|
|
1. **Build**: Compile for your target architecture (see CI/CD artifacts).
|
|
2. **Deploy**: Place the binary in `/usr/local/bin/theta-agent`.
|
|
3. **Enroll**: In the SSO, open **Directory → Install Agent**, name the host, bind
|
|
it to a host resource, and press **Enroll & issue token**. The SSO mints the
|
|
token (shown once) and gives you its public key. Tokens the server did not
|
|
issue are rejected.
|
|
4. **Configure**: Create `/etc/theta42/agent.yml` with the issued `auth_token`,
|
|
the SSO's `public_key`, and your capabilities.
|
|
4. **Service**: Set up as a systemd unit (example: `/etc/systemd/system/theta-agent.service`).
|
|
|
|
For the fastest deployment, use the installation script:
|
|
```bash
|
|
curl -fsSL https://sso.example.com/resources/theta-agent/install.sh | sh -s -- "BASE64_ENCODED_CONFIG"
|
|
```
|
|
|
|
The **Install Agent** modal generates that command for you after enrollment,
|
|
with the token and public key already embedded. The equivalent flag form is:
|
|
|
|
```bash
|
|
curl -fsSL https://sso.example.com/resources/theta-agent/install.sh | sh -s -- \
|
|
--url "https://sso.example.com" --token "<ISSUED_TOKEN>" --public-key "<BASE64_PUBLIC_KEY>"
|
|
```
|
|
|
|
## Development & Testing
|
|
|
|
The agent uses a decoupled execution engine for safety and testability.
|
|
- Run unit tests: `go test -v ./...`
|
|
- The test suite uses a `MockExecutor` to verify that system commands are only triggered when the corresponding capability is enabled in the configuration.
|