NewLife/Stardust

README.md
# StarAgent Native (Rust) StarAgent 的 Rust 原生实现,遵循 [`../spec/protocol.md`](/NewLife/Stardust/Blob/master/StarAgent.Native/rust/../spec/protocol.md) 与 [`../spec/schemas/node-agent.schema.json`](/NewLife/Stardust/Blob/master/StarAgent.Native/rust/../spec/schemas/node-agent.schema.json), 行为与 [`../go`](/NewLife/Stardust/Blob/master/StarAgent.Native/rust/../go) 参考实现对齐。 ## 已实现能力 - 登录 / 注销 / 心跳 / 令牌续期 / `NewServer` 迁移 / 指数退避重连(1s→30s,带抖动) - HTTP:`/node/login`、`/node/logout`、`/node/ping`、`/node/postevents`、 `/node/commandreply`、`/node/upgrade` - WebSocket:`/node/notify`(`Authorization: Bearer`),文本 `Ping`/`Pong` 保活, JSON `CommandModel` 执行后通过 HTTP 回复 - 心跳响应中的 `Commands`(HTTP 降级)执行 - 指标:CPU、内存、磁盘容量/挂载点、网络速率、进程数/进程名、运行时长、系统负载; 单项采集失败填 0,不影响心跳 - 命令:按 `Id` 去重 1 小时、过期取消、`StartTime` 延迟执行、默认 30s 超时(最大 300s)、 输出 64KB 头尾截断、进程树终止、最多 4 个并发(shell 串行) - 内置命令:`bash`(Unix)、`cmd`(Windows)、`node/synctime`、 `node/setchannel`、`node/restart`;`node/reboot`、`deploy/*`、`framework/install` 返回“不支持命令” - 安全默认 `AllowExec=false`;开启后仍受 `AllowedCommands` 白名单、8KB 参数上限、 超时与 64KB 输出上限约束 - 配置文件 `staragent.json` + `STARAGENT_` 环境变量覆盖;`Code`/`Secret` 原子持久化, 权限 `0600`;日志按天滚动并保留 7 天 - CLI:`run`、`once`、`version`、`install`、`uninstall`、`start`、`stop`、`status` - 服务形态:Linux systemd、OpenWrt procd、macOS launchd、Windows Service (`windows-service`,服务名 `StarAgentNative`) ## 目录 ``` src/ ├── main.rs CLI 入口、服务检测、信号处理 ├── app.rs 配置装载、日志初始化、启动参数覆盖 ├── config.rs 配置、环境变量、原子持久化(0600) ├── protocol.rs PascalCase JSON 模型、时间格式、响应包装解析 ├── client.rs HTTP 客户端、令牌、401 重新登录、退避 ├── notify.rs WebSocket /node/notify、Ping/Pong、命令解析 ├── metrics.rs sysinfo 指标采集与失败降级 ├── identity.rs 稳定硬件标识、网络与系统信息 ├── command/ 命令执行、去重、白名单、超时、输出截断、平台实现 ├── agent.rs 登录/心跳/迁移/事件/命令主循环 ├── events.rs 有界事件队列(落盘 events.json) ├── logging.rs 按天轮转日志 └── service.rs systemd / procd / launchd / Windows 服务 ``` ## 构建 需要 Rust 1.82+(本仓库使用 stable 工具链验证)。 ```powershell cd StarAgent.Native\rust cargo build --release cargo test cargo fmt --check ``` 如果 crates.io 下载超时,可在**本地**(不要提交)创建 `.cargo/config.toml` 使用 rsproxy 稀疏镜像;CI 与普通用户默认直接使用 crates.io: ```toml [source.crates-io] replace-with = "rsproxy-sparse" [source.rsproxy-sparse] registry = "sparse+https://rsproxy.cn/index/" ``` 产物:`target\release\staragent.exe`(Windows)或 `target/release/staragent`。 构建信息可通过环境变量覆盖版本号: ```powershell $env:STARAGENT_VERSION = "1.0.2026.1017" cargo build --release ``` `build.rs` 会把版本与构建时间写入二进制,`NodeInfo.Compile` 使用构建时间。 ### 交叉编译 TLS 使用 rustls + ring(不依赖 OpenSSL),纯 Rust 依赖便于交叉编译: ```bash rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl cargo build --release --target x86_64-unknown-linux-musl cargo build --release --target aarch64-unknown-linux-musl rustup target add x86_64-apple-darwin aarch64-apple-darwin cargo build --release --target x86_64-apple-darwin cargo build --release --target aarch64-apple-darwin ``` `ring` 包含 C/汇编代码,交叉编译需要目标平台的 C 工具链: - Linux musl:安装 `musl-gcc`(Debian/Ubuntu:`apt install musl-tools`),或使用 `cargo install cargo-zigbuild` + Zig 后执行 `cargo zigbuild --release --target x86_64-unknown-linux-musl`。 - macOS:需要 Apple SDK 与 Xcode command line tools,通常只能在 macOS 上构建。 - Windows x64:在 Windows 上使用 MSVC 工具链直接构建。 缺少工具链时 `cargo build` 会明确报错,本项目不会把未生成的产物标记为成功。 ## 配置 默认读取当前目录 `staragent.json`(可用 `--config` 或 `STARAGENT_CONFIG` 覆盖): ```json { "Server": "https://star.example.com:6600", "ProductCode": "StarAgent-Rust", "Code": "", "Secret": "", "Project": "", "Channel": "Release", "DataDir": "/var/lib/staragent", "LogLevel": "info", "MetricsInterval": 60, "AllowExec": false, "AllowedCommands": [], "CommandTimeout": 30, "TlsVerify": true } ``` 约束:`MetricsInterval` 5~3600 秒;`CommandTimeout` 1~300 秒;`Server` 必须是 `http://` 或 `https://`。心跳实际周期以服务端 `PingResponse.Period` 为准(下限 1 秒)。 环境变量(前缀 `STARAGENT_`,同时兼容下划线写法): | 变量 | 示例 | |------|------| | `STARAGENT_SERVER` / `STARAGENT_SERVER_URL` | `https://star.example.com:6600` | | `STARAGENT_PRODUCTCODE` / `STARAGENT_PRODUCT_CODE` | `StarAgent-Rust` | | `STARAGENT_CODE` / `STARAGENT_SECRET` | 已注册节点身份 | | `STARAGENT_PROJECT` | `demo` | | `STARAGENT_CHANNEL` | `Release` | | `STARAGENT_DATADIR` / `STARAGENT_DATA_DIR` | `/var/lib/staragent` | | `STARAGENT_LOGLEVEL` / `STARAGENT_LOG_LEVEL` | `debug` | | `STARAGENT_METRICSINTERVAL` / `STARAGENT_METRICS_INTERVAL` | `60` | | `STARAGENT_ALLOWEXEC` / `STARAGENT_ALLOW_EXEC` | `false` | | `STARAGENT_ALLOWEDCOMMANDS` / `STARAGENT_ALLOWED_COMMANDS` | `node/*,bash`(逗号或分号分隔) | | `STARAGENT_COMMANDTIMEOUT` / `STARAGENT_COMMAND_TIMEOUT` | `30` | | `STARAGENT_TLSVERIFY` / `STARAGENT_TLS_VERIFY` | `true` | `Code`/`Secret` 只由登录响应写入文件;`Token` 仅保存在内存,不落盘。 `AllowedCommands` 支持精确名称与后缀 `*`(例如 `node/*`)。 ## 运行 ```bash ./staragent run --config /opt/staragent/staragent.json ./staragent once --config ./staragent.json # 登录、心跳、处理命令后退出 ./staragent version ``` 命令执行默认关闭。需要时显式开启,并建议同时配置白名单: ```bash ./staragent run --allow-exec --config /opt/staragent/staragent.json ``` ## 安装为服务 ### Linux(systemd) ```bash sudo ./staragent install --server https://star.example.com:6600 \ --config /opt/staragent/staragent.json --dir /opt/staragent --user staragent sudo ./staragent status ``` 生成 `/etc/systemd/system/staragent.service`,包含 `Restart=always`、 `KillSignal=SIGTERM`,并执行 `systemctl daemon-reload` / `enable`。需要 root。 ### OpenWrt(procd) 检测到 `/etc/openwrt_release` 时,`install` 改为生成 `/etc/init.d/staragent` (`start_service` / `stop_service` / `procd_set_param respawn`)。建议使用 musl 静态构建。 ### macOS(launchd) root 安装写入 `/Library/LaunchDaemons/com.newlifex.staragent.plist`; 普通用户写入 `~/Library/LaunchAgents/com.newlifex.staragent.plist`。 `start` / `stop` 使用 `launchctl load -w` / `unload -w`。 ### Windows 以管理员身份执行: ```powershell .\staragent.exe install --server https://star.example.com:6600 ` --config C:\ProgramData\StarAgent\bin\staragent.json .\staragent.exe start .\staragent.exe status .\staragent.exe uninstall ``` 服务名 `StarAgentNative`,由 SCM 启动 `run` 时自动进入服务模式 (`windows-service` 的 `service_dispatcher`)。 ## HTTPS / WSS - HTTP 请求与 WebSocket 握手统一使用 rustls + ring(不依赖 OpenSSL),便于静态/交叉构建。 - `Server` 为 `https://` 时,`/node/notify` 自动使用 `wss://`;`Authorization: Bearer` 头同时用于 HTTP 与 WS 握手。 - `TlsVerify=true`(默认)使用 webpki 内置根证书校验服务端证书;`false` 关闭校验,仅用于测试环境。 - 当前版本使用内置根证书,不读取系统证书库,也不支持自定义 CA 文件;使用企业私有 CA 时需自行构建或改用受信任证书(见“已知限制”)。 ## 一致性测试 ```powershell cd StarAgent.Native\conformance go build -o conformance.exe ./cmd/conformance .\conformance.exe --agent ..\rust\target\release\staragent.exe ` --config .\templates\agent.json --scenario all --workdir ..\rust\target\conformance ``` 目标:6 passed / 0 failed。runner 默认执行 `run --config <file>`,并通过环境变量 `STARAGENT_SERVER`、`STARAGENT_DATA_DIR`、`STARAGENT_PRODUCTCODE` 注入配置。 本实现在 Windows(release 构建)上使用 `--scenario all` 实测结果为 **6 passed / 0 failed**:`basic`、`http-fallback`、`dedup`、`expired`、`reconnect`、`events`。 ## 安全说明 - 生产环境保持 `TlsVerify=true`;`false` 仅用于测试。 - 日志不输出 `Secret`、`Token` 与命令完整参数;审计日志只记录命令名、Id、 状态、耗时与参数字节数。 - shell 命令默认关闭;开启后仍受白名单、8KB 参数上限、超时与 64KB 输出上限约束。 - `node/restart` 使用当前可执行文件与原始参数重新拉起进程后退出。 - 配置、事件队列使用临时文件 + rename 原子写入;Unix 下配置权限 `0600`(Windows 依赖 ACL)。 ## 已知限制 - 首版不自动升级:`/node/upgrade` 有可用版本时仅记录日志并上报 `Upgrade` 事件。 - `node/reboot`、`deploy/*`、`framework/install` 明确返回不支持。 - `node/synctime` 需要 root/管理员权限,失败会返回错误与 stderr 摘要。 - 在 systemd/launchd 下使用 `node/restart` 时,监督进程可能同时拉起实例; 生产环境建议改用 `systemctl restart staragent` 等外部编排。 - Windows 服务模式下 `node/restart` 拉起的是普通进程而非 SCM 服务实例,需要外部服务管理器兜底。 - Android/iOS 不在本目录范围内。 - 指标中的 `Temperature`、`Battery`、`TcpConnections`、`GatewayLatency` 等字段 当前固定为 0(协议允许缺失填 0)。 - TLS 使用 webpki 内置根证书,不读取系统证书库,暂不支持自定义 CA 文件;企业私有 CA 场景需换用受信任证书或自行扩展 `Client` 的 TLS 配置。 - Linux/macOS 交叉构建需要目标平台的 C 工具链(`ring` 含 C/汇编代码): `x86_64-unknown-linux-musl` 需要 `musl-gcc` 或 `cargo-zigbuild` + Zig; macOS 目标需要 Apple SDK。缺少工具链时构建会失败并给出明确错误。