- Workspace: common (protocol/crypto/tarball), server (axum+rustls), stub (registration, poll, verify-before-execute) - Ed25519 payload signing + request-signature auth on /poll, /report - flate2/miniz_oxide pure-Rust tarball, no system deps - CI matrix: linux musl x86_64/aarch64, windows x86_64 - Compiles clean: cargo build --workspace, 0 errors 0 warnings
3.3 KiB
3.3 KiB
Deploy-Agent — Build Spec
A deployment automation system: a lightweight stub agent that runs on target machines, polls a control server over HTTPS:443, downloads signed payloads, verifies signatures, and executes them. Rust everywhere.
Project root
/home/node/.openclaw/workspace/tools/deploy-agent/
Layout:
tools/deploy-agent/
├── Cargo.toml # workspace: members = ["server", "stub", "common"]
├── common/ # shared crate: protocol types, crypto, payload format
├── server/ # control server
├── stub/ # target-machine agent
├── payloads/ # sample payload tarballs + signing scripts
├── README.md # architecture, threat model, build, deploy
└── justfile or Makefile # build targets
Targets
- Linux x86_64 (primary) — musl static, rustls
- Linux aarch64 — musl static, rustls
- Windows x86_64 — Win 10/11, rustls (NOTE: modern Rust 1.94 has NO win7 targets; protocol must stay OS-agnostic so a legacy win7 build can be added later without server changes)
Stub behavior (stub/)
- Register once on first run: generate Ed25519 identity keypair, send public key + machine ID → server issues per-machine client cert (or server stores pubkey for challenge). Same ID reused on subsequent runs.
- Poll
POST /pollwith machine id + auth. Server returns instruction or "no-op". - Instruction types (whitelist, NOT raw shell):
fetch-payload: download tarball from server, verify Ed25519 signature, extractrun-payload: execute the verified payload (a bundled script/binary per-platform)report-status: return result + logs to server
- TLS: rustls (Linux/Windows). No OpenSSL for Linux (stays static). Windows 10/11 uses rustls too.
- Compression: flate2 with miniz_oxide backend (pure Rust, zero system deps).
Server behavior (server/)
- axum + rustls + rustls-acme (Let's Encrypt auto-provision on :443)
- mTLS client cert auth for stubs
- Per-machine instruction store (JSON file or SQLite) — which machine has which payload revision
- Endpoints:
POST /register— initial machine registrationPOST /poll— authenticated stub polls for instructionsGET /payload/{id}— served over mTLS, stub downloads tarball- Admin UI or CLI to push instructions to a machine
- Signature key: server holds Ed25519 signing key; publishes public key for payload verification
Security model (must document in README)
- mTLS machine auth (client certs issued at registration)
- Payloads signed with Ed25519 — stub verifies before ANY execution
- Whitelisted instruction set, NOT arbitrary remote shell
- All traffic over TLS 1.3 (rustls)
- Defense-in-depth: even a compromised server can't push unsigned payloads
Deliverables
- Rust workspace that compiles
- Stub binary for each target (Linux musl static confirmed)
- Server binary + Let's Encrypt provisioning
- Payload signing helper script
- README with threat model + build/run instructions
- .gitea/workflows/ CI to build the target matrix
Constraints
- No system lib dependencies for Linux (musl static)
- flate2/miniz_oxide for compression (pure Rust)
- rustls for TLS everywhere possible
- Ed25519 (via ed25519-dalek or ring) for signing
- Keep protocol/format identical across all OS targets
- This is security-sensitive: verify-before-execute is non-negotiable