Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
319 lines
12 KiB
Markdown
319 lines
12 KiB
Markdown
# Secure Local Payload Validation
|
||
|
||
End-to-end validation of a forged AetherForge agent **without risking production keys or your daily driver**. This playbook recommends one primary path and tiered alternatives.
|
||
|
||
---
|
||
|
||
## Verdict: Docker Windows vs Disposable VM
|
||
|
||
| Environment | Server | Linux agent | Windows agent (full payload) |
|
||
|-------------|--------|-------------|------------------------------|
|
||
| **Host + Hyper-V VM** (recommended) | ✅ `devrun.bat` on host | ✅ optional WSL2 VM | ✅ real Win32, WMI, USB, desktop, GPU |
|
||
| **Linux Docker** | ✅ Go binary in container | ✅ partial C2 + mining | ❌ cannot compile/run Windows agent features |
|
||
| **Docker Desktop Windows containers** | ⚠️ awkward (Server Core image) | N/A | ❌ **poor fit** — see below |
|
||
|
||
### Why not Docker Windows for full payload tests?
|
||
|
||
Windows containers run on **Windows Server Core** (or similar) with a different kernel contract than desktop Windows:
|
||
|
||
- **No interactive desktop** — screenshots, clipboard, and many PowerShell UI calls fail or return empty.
|
||
- **WMI USB subscriptions, autorun.inf, LNK spread, Defender tampering** — require desktop-class Windows and often admin on a real session.
|
||
- **GPU mining (T-Rex / TeamRedMiner)** — no practical NVIDIA/AMD passthrough in Windows containers.
|
||
- **USB propagation** — container cannot see host removable drives the way a VM or bare metal can.
|
||
- **WinRM / SMB lateral spread** — needs a multi-machine lab network, not an isolated container namespace.
|
||
|
||
**Honest recommendation:** use **Docker/Linux only for server + automated CI**. For **full Windows payload validation**, use a **disposable Hyper-V (or VMware) Windows 10/11 VM** — or a dedicated second physical “burner” PC — then **revert a snapshot** when done.
|
||
|
||
---
|
||
|
||
## Tiered Test Matrix
|
||
|
||
### Tier 0 — Mining stack only (no C2, no payload)
|
||
|
||
Proves RandomX + pool worker + optional live Stratum **on the dev machine**.
|
||
|
||
```powershell
|
||
cd agent
|
||
go run ./cmd/mine-validate -seconds 20 -threads 2
|
||
```
|
||
|
||
| Validates | Does not validate |
|
||
|-----------|-------------------|
|
||
| RandomX engine, pool workers, live pool login | C2 WebSocket, forge bake, persistence, spread |
|
||
|
||
> **Note:** `mine-validate` may spam `[miner] hash error: randomx VM not initialized` during the multi-threaded pool phase while still reporting non-zero H/s and exiting 0. Treat non-zero hashrate + exit 0 as pass; investigate if exit code is 1.
|
||
|
||
### Tier 1 — Automated CI (no real agent)
|
||
|
||
```bat
|
||
test.bat
|
||
```
|
||
|
||
Or faster (skip builds + Playwright):
|
||
|
||
```powershell
|
||
.\scripts\test-suite.ps1 -SkipBuild -SkipE2E
|
||
```
|
||
|
||
| Phase | Coverage |
|
||
|-------|----------|
|
||
| Go server + agent unit/integration tests | API, forge, auth, pool, fusion |
|
||
| Vitest | Dashboard forms, preflight, offline gating |
|
||
| Playwright (`-SkipE2E` off) | Login smoke, mocked fleet UI |
|
||
|
||
Also with server already running:
|
||
|
||
```powershell
|
||
.\scripts\smoke-test.ps1 -BaseUrl http://127.0.0.1:8989
|
||
```
|
||
|
||
### Tier 2 — Server + Linux agent (same host, Linux VM, or Docker)
|
||
|
||
Good for **C2 path**, basic recon, mining install, systemd persistence — **not** Windows-only ops.
|
||
|
||
**Option A — Docker (isolated bridge, recommended for CI)**
|
||
|
||
```bash
|
||
# Automated proof (compose up + assert + teardown)
|
||
scripts/ci-docker-mining.sh # Linux / macOS / GHA
|
||
.\scripts\ci-docker-mining.ps1 # Windows + Docker Desktop
|
||
```
|
||
|
||
Or interactive:
|
||
|
||
```bash
|
||
docker compose -f docker/docker-compose.yml up --build
|
||
```
|
||
|
||
- Server on host port **18989**; dashboard `testuser` / `testpass` (see `docker/data/users.json`).
|
||
- Fleet secret `e2e-docker-fleet-secret-fixed001` in `docker/data/config.json` + `docker/agent-builtin.go`.
|
||
- Test wallet in `docker/data/config.json` and `docker/agent-builtin.go` (see E2E test address in security rules above).
|
||
- Agent container has **no internet egress** — mines via server-broadcast jobs only.
|
||
- RandomX is pure Go (`go-randomx`); agent image needs **no CGO**.
|
||
- **Assert logic:** `GET /api/v1/health` → `GET /api/v1/agents` (Basic auth) finds `status=online` with `hashrate_15s|1m|15m > 0`, or `GET /api/v1/dashboard/stats` shows `online_agents >= 1` and `total_hashrate > 0`. Waits up to **3 minutes**.
|
||
- GitHub Actions: `.github/workflows/ci-docker-mining.yml` on every push (`ubuntu-latest`).
|
||
- Verify manually: Fleet Roster shows `docker-e2e-linux`; hashrate fields populate after ~30s.
|
||
- Teardown: `docker compose -f docker/docker-compose.yml down --rmi local -v`
|
||
|
||
Full notes: [`docker/README.md`](../docker/README.md).
|
||
|
||
**Option B — WSL2 / Linux VM**
|
||
|
||
1. Start server on host: `devrun.bat`
|
||
2. Forge **Linux amd64** worker pointing at `http://<host-lan-ip>:8989` (VM must reach host; bind server to LAN or use Hyper-V Default Switch IP).
|
||
3. Run agent in WSL2 or a small Linux VM.
|
||
4. Crucible: `sysinfo`, `pause`/`resume`, `get_log`, `list_dir` (Linux file ops).
|
||
|
||
### Tier 3 — Full Windows payload (primary E2E path)
|
||
|
||
**Topology**
|
||
|
||
```
|
||
┌─────────────────────────────┐ ┌──────────────────────────────┐
|
||
│ Host PC (control) │ LAN │ Disposable Win10/11 VM │
|
||
│ devrun.bat → :8989 │◄───────►│ forged test agent.exe │
|
||
│ data/ logs, builds, DB │ only │ snapshot "clean" → revert │
|
||
└─────────────────────────────┘ └──────────────────────────────┘
|
||
```
|
||
|
||
**Security rules**
|
||
|
||
1. **Dedicated test data dir** — e.g. `data-e2e\` with fresh `users.json`; never copy production `data\`.
|
||
2. **Test wallet** — use the repo's recommended E2E Monero address (public test wallet, not for production):
|
||
|
||
`85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm`
|
||
|
||
Seeded automatically in `data-e2e/config.json` by `scripts/e2e-validate.ps1` and in `docker/data/config.json` for Tier 2 Docker. Do not use your production wallet.
|
||
3. **Rotate fleet secret** after tests if you ever pointed at shared `data\`.
|
||
4. **No internet egress from VM** (optional but ideal) — allow only host IP:8989 + pool Stratum if testing live shares.
|
||
5. **Snapshot before forge run** — revert VM when finished (“toss the machine”).
|
||
|
||
---
|
||
|
||
## Step-by-Step: Tier 3 Playbook
|
||
|
||
### 1. Prepare isolated server data
|
||
|
||
```powershell
|
||
$env:AETHERFORGE_E2E_USER = "testuser"
|
||
$env:AETHERFORGE_E2E_PASS = "testpass"
|
||
New-Item -ItemType Directory -Force -Path ".\data-e2e" | Out-Null
|
||
'{"testuser":"testpass"}' | Set-Content ".\data-e2e\users.json" -Encoding UTF8
|
||
```
|
||
|
||
Start server against that directory (from repo root):
|
||
|
||
```bat
|
||
bin\miner-server.exe -port 8989 -data .\data-e2e
|
||
```
|
||
|
||
Or use `devrun.bat` after pointing `-data` at `data-e2e` (or run `.\scripts\e2e-validate.ps1 -PrepareOnly`).
|
||
|
||
### 2. Calibrate for validation
|
||
|
||
In **Calibrate** (Settings):
|
||
|
||
| Setting | Test value |
|
||
|---------|------------|
|
||
| Server URL | `http://<host-ip>:8989` (must match what the VM can reach) |
|
||
| Wallet | `85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm` (or match `data-e2e/config.json`) |
|
||
| `file_logging` | **true** (required for `get_log` / `data-e2e\logs\`) |
|
||
| Stealth mode | **off** for first pass (easier debugging) |
|
||
| USB / share / auto-spread | **off** until spread is explicitly under test |
|
||
| Remote aggressive ops | **on** only in a VM snapshot you will revert |
|
||
| `agent_kill_after_days` | optional safety fuse (e.g. `1`) |
|
||
|
||
### 3. Forge a test worker
|
||
|
||
In **Forge**:
|
||
|
||
- Target OS: **Windows amd64**
|
||
- Worker name: `e2e-validate`
|
||
- Enable only features you intend to test this session
|
||
- Download `e2e-validate.exe` + paired `uninstall-e2e-validate.ps1`
|
||
|
||
Or use the orchestrator script (API forge) after server is up:
|
||
|
||
```powershell
|
||
.\scripts\e2e-validate.ps1 -ForgeAgent
|
||
```
|
||
|
||
### 4. Hyper-V VM setup (Windows)
|
||
|
||
```powershell
|
||
# Example: Hyper-V Manager or PowerShell
|
||
# 1. Create Gen2 VM, 4 GB RAM, 40 GB disk
|
||
# 2. Internal or Default Switch network (host reachable)
|
||
# 3. Take snapshot named "clean-pre-agent"
|
||
# 4. Copy forged exe into VM (shared folder or ISO)
|
||
```
|
||
|
||
**Before running the agent:** snapshot name recorded, VM has no personal data, Defender policy acceptable for your lab.
|
||
|
||
### 5. Run agent in VM
|
||
|
||
1. Execute forged exe once (install + connect).
|
||
2. Confirm agent appears on dashboard **Fleet Roster** (online).
|
||
3. Check server console for `[agent] authenticated`.
|
||
|
||
### 6. Crucible command checklist
|
||
|
||
Run against the test agent. Tick as you go.
|
||
|
||
**Core / mining**
|
||
|
||
- [ ] `sysinfo` — hostname, cores, RAM
|
||
- [ ] `pause` / `resume` / `restart` — miner control
|
||
- [ ] `connectivity_probe` — C2 + pool reachability JSON
|
||
- [ ] `get_log` — tail returns `miner.log` lines
|
||
|
||
**Recon (Windows)**
|
||
|
||
- [ ] `ps`, `netstat`, `listen_ports`
|
||
- [ ] `ipconfig`, `wifi`, `posture`, `patch_status`
|
||
- [ ] `screenshot` (needs interactive logged-in desktop)
|
||
- [ ] `camera_list` / `camera_snapshot` (needs ffmpeg + camera)
|
||
|
||
**Files (Windows)**
|
||
|
||
- [ ] `list_dir` — `C:\Users\<user>\`
|
||
- [ ] `read_file` — small text file
|
||
- [ ] `upload` / `download` round-trip
|
||
|
||
**Power / lifecycle**
|
||
|
||
- [ ] `exec` / `powershell` — benign echo command
|
||
- [ ] `reboot_machine` — only if snapshot revert planned
|
||
- [ ] `uninstall` or run `uninstall-*.ps1` — M-10 checklist
|
||
|
||
**Advanced (enable in forge + revert snapshot after)**
|
||
|
||
- [ ] `get_wifi_passwords`, `defender_off`, `firewall_*`
|
||
- [ ] USB spread — second USB passthrough device
|
||
- [ ] `spread_now` / LAN spread — requires second lab VM
|
||
|
||
### 7. Collect logs
|
||
|
||
| Source | Path / action |
|
||
|--------|----------------|
|
||
| Server stdout | `devrun.bat` window |
|
||
| Server agent log cache | `data-e2e\logs\<agent-id>.log` |
|
||
| Agent on disk | `%LOCALAPPDATA%\<install-dir>\miner.log` |
|
||
| Dashboard | Fleet → Remote Control → **Fetch Log** |
|
||
| API | `GET /api/v1/agents/{id}/log?refresh=1` |
|
||
|
||
```powershell
|
||
Get-ChildItem ".\data-e2e\logs\"
|
||
Get-Content ".\data-e2e\logs\<agent-id>.log" -Tail 100
|
||
```
|
||
|
||
### 8. Teardown (“toss the machine”)
|
||
|
||
1. **VM:** Hyper-V → **Revert to snapshot** `clean-pre-agent` (or delete VM).
|
||
2. **Host:** stop server; archive or delete `data-e2e\` if no longer needed.
|
||
3. **Network:** remove any temporary firewall rules allowing VM→host:8989.
|
||
4. **Secrets:** if production `data\` was ever used, rotate fleet secret in Calibrate.
|
||
|
||
---
|
||
|
||
## Quick orchestration
|
||
|
||
```powershell
|
||
# Automated tiers 0–1 + instructions for tier 3
|
||
.\scripts\e2e-validate.ps1
|
||
|
||
# Tier 0 only
|
||
.\scripts\e2e-validate.ps1 -SkipAutomatedTests -SkipServerCheck
|
||
|
||
# Prepare test data + print checklist (no forge)
|
||
.\scripts\e2e-validate.ps1 -PrepareOnly
|
||
```
|
||
|
||
---
|
||
|
||
## What each existing tool covers
|
||
|
||
| Tool | Tier | Scope |
|
||
|------|------|-------|
|
||
| `agent/cmd/mine-validate` | 0 | Mining only |
|
||
| `test.bat` / `scripts/test-suite.ps1` | 1 | Full automated suite |
|
||
| `scripts/smoke-test.ps1` | 1 | REST B-01–B-10 |
|
||
| `scripts/ci-docker-mining.sh` / `.ps1` | 2 | Docker Linux agent hashrate proof |
|
||
| `.github/workflows/ci-docker-mining.yml` | 2 | GHA push gate |
|
||
| `server/web/e2e/*.spec.ts` | 1 | Dashboard smoke (mocked WS) |
|
||
| `docs/TEST_RESULTS.md` | 1–3 | Matrix IDs; M-01–M-09 manual |
|
||
| `devrun.bat` | 2–3 | Build + launch control server |
|
||
| Forge + burner VM | 3 | Full payload |
|
||
|
||
---
|
||
|
||
## Linux vs Windows agent capabilities (validation scope)
|
||
|
||
| Feature | Windows | Linux | macOS |
|
||
|---------|---------|-------|-------|
|
||
| RandomX CPU mining + dashboard hashrate | ✅ | ✅ | ✅ |
|
||
| GPU RVN mining | ✅ | stub (detect only) | stub |
|
||
| Screenshot | ✅ (GDI+) | ✅ (scrot/import/gnome-screenshot) | ✅ (screencapture) |
|
||
| Camera | ✅ (ffmpeg) | ✅ (V4L2/ffmpeg/fswebcam) | stub |
|
||
| Clipboard | ✅ | ✅ (xclip/pbpaste) | ✅ (pbpaste) |
|
||
| File browser Crucible | ✅ | ✅ | ✅ |
|
||
| Posture / syscheck | ✅ (WMI) | ✅ (ufw/systemd/apt) | partial |
|
||
| Firewall aggressive ops | ✅ (netsh) | ✅ (ufw/iptables) | stub |
|
||
| USB / WMI spread | ✅ | ❌ | ❌ |
|
||
| SMB / WinRM spread | ✅ | ❌ | ❌ |
|
||
| SSH lateral spread | ❌ | ✅ | ✅ |
|
||
| WiFi password harvest | ✅ | stub | stub |
|
||
| Defender off | ✅ | N/A (returns error) | N/A |
|
||
| systemd / LaunchAgent persistence | — | ✅ | ✅ |
|
||
| Idle-mode mining (CPU % sample) | ✅ | ✅ (fixed: /proc/stat) | ✅ (sysctl kern.cp_time) |
|
||
|
||
Use **Tier 3 Windows VM** when validating spread, GPU, screenshot, or aggressive ops. Use **Tier 2 Linux** for faster C2 regression on recon + mining.
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- Automated test phases: `tests/README.md`
|
||
- Manual matrix IDs: `docs/TEST_RESULTS.md` (M-01–M-10)
|
||
- Known gaps: `PROBLEMS.md`
|