Some checks failed
Secrets CLI - Build & Release / 版本 & Release (push) Successful in 3s
Secrets CLI - Build & Release / 质量检查 (fmt / clippy / test) (push) Successful in 1m17s
Secrets CLI - Build & Release / 通知 (push) Successful in 6s
Secrets CLI - Build & Release / 发布草稿 Release (push) Has been cancelled
Secrets CLI - Build & Release / Build (aarch64-apple-darwin) (push) Has started running
Secrets CLI - Build & Release / Build (x86_64-pc-windows-msvc) (push) Has been cancelled
Secrets CLI - Build & Release / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
- tracing + tracing-subscriber,全局 --verbose/-v 与 RUST_LOG 控制 - 新增 audit_log 表,add/update/delete 成功后自动写入审计记录 - 新增 src/audit.rs,审计失败仅 warn 不中断主流程 - 更新 README/AGENTS.md,补充 verbose、audit_log 说明 - .vscode/tasks.json 增加 verbose/update/audit 测试任务 Made-with: Cursor
230 lines
9.1 KiB
Markdown
230 lines
9.1 KiB
Markdown
# Secrets CLI — AGENTS.md
|
||
|
||
跨设备密钥与配置管理 CLI 工具,将 refining / ricnsmart 两个项目的服务器信息、服务凭据存储到 PostgreSQL 18,供 AI 工具读取上下文。
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
secrets/
|
||
src/
|
||
main.rs # CLI 入口,clap 命令定义,auto-migrate,--verbose 全局参数
|
||
config.rs # 配置读写:~/.config/secrets/config.toml(database_url)
|
||
db.rs # PgPool 创建 + 建表/索引(幂等,含 audit_log)
|
||
models.rs # Secret 结构体(sqlx::FromRow + serde)
|
||
audit.rs # 审计写入:向 audit_log 表记录所有写操作
|
||
commands/
|
||
add.rs # add 命令:upsert,支持 --meta key=value / --secret key=@file
|
||
config.rs # config 命令:set-db / show / path(持久化 database_url)
|
||
search.rs # search 命令:多条件动态查询
|
||
delete.rs # delete 命令
|
||
update.rs # update 命令:增量更新(合并 tags/metadata/encrypted)
|
||
scripts/
|
||
seed-data.sh # 从 refining/ricnsmart config.toml 导入全量数据
|
||
.gitea/workflows/
|
||
secrets.yml # CI:fmt + clippy + musl 构建 + Release 上传 + 飞书通知
|
||
.vscode/tasks.json # 本地测试任务(build / config / search / add+delete / update / audit 等)
|
||
```
|
||
|
||
## 数据库
|
||
|
||
- **Host**: `47.117.131.22:5432`(阿里云上海 ECS,PostgreSQL 18 with io_uring)
|
||
- **Database**: `secrets`
|
||
- **连接串**: `postgres://postgres:<password>@47.117.131.22:5432/secrets`
|
||
- **表**: `secrets`(主表)+ `audit_log`(审计表),首次连接自动建表(auto-migrate)
|
||
|
||
### 表结构
|
||
|
||
```sql
|
||
secrets (
|
||
id UUID PRIMARY KEY DEFAULT uuidv7(), -- PG18 时间有序 UUID
|
||
namespace VARCHAR(64) NOT NULL, -- 一级隔离: "refining" | "ricnsmart"
|
||
kind VARCHAR(64) NOT NULL, -- 类型: "server" | "service"(可扩展)
|
||
name VARCHAR(256) NOT NULL, -- 人类可读标识
|
||
tags TEXT[] NOT NULL DEFAULT '{}', -- 灵活标签: ["aliyun","hongkong"]
|
||
metadata JSONB NOT NULL DEFAULT '{}', -- 明文描述: ip, desc, domains, location...
|
||
encrypted JSONB NOT NULL DEFAULT '{}', -- 敏感数据: ssh_key, password, token...
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
UNIQUE(namespace, kind, name)
|
||
)
|
||
```
|
||
|
||
### audit_log 表结构
|
||
|
||
```sql
|
||
audit_log (
|
||
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||
action VARCHAR(32) NOT NULL, -- 'add' | 'update' | 'delete'
|
||
namespace VARCHAR(64) NOT NULL,
|
||
kind VARCHAR(64) NOT NULL,
|
||
name VARCHAR(256) NOT NULL,
|
||
detail JSONB NOT NULL DEFAULT '{}', -- 变更摘要(tags/meta keys/secret keys,不含 value)
|
||
actor VARCHAR(128) NOT NULL DEFAULT '', -- 操作者($USER 环境变量)
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
)
|
||
```
|
||
|
||
### 字段职责划分
|
||
|
||
| 字段 | 存什么 | 示例 |
|
||
|------|--------|------|
|
||
| `namespace` | 项目/团队隔离 | `refining`, `ricnsmart` |
|
||
| `kind` | 记录类型 | `server`, `service` |
|
||
| `name` | 唯一标识名 | `i-uf63f2uookgs5uxmrdyc`, `gitea` |
|
||
| `tags` | 多维分类标签 | `["aliyun","hongkong","ricn"]` |
|
||
| `metadata` | 明文非敏感信息 | `{"ip":"47.243.154.187","desc":"Grafana","domains":["..."]}` |
|
||
| `encrypted` | 敏感凭据(MVP 阶段明文存储,后续对 value 加密) | `{"ssh_key":"-----BEGIN...","password":"..."}` |
|
||
|
||
## 数据库配置
|
||
|
||
首次使用需显式配置数据库连接,设置一次后在该设备上持久生效:
|
||
|
||
```bash
|
||
secrets config set-db "postgres://postgres:<password>@47.117.131.22:5432/secrets"
|
||
secrets config show # 查看当前配置(密码脱敏)
|
||
secrets config path # 打印配置文件路径
|
||
```
|
||
|
||
配置文件:`~/.config/secrets/config.toml`,权限 0600。`--db-url` 参数可一次性覆盖。
|
||
|
||
## CLI 命令
|
||
|
||
```bash
|
||
# 查看版本
|
||
secrets -V / --version
|
||
|
||
# 查看帮助
|
||
secrets -h / --help
|
||
secrets help <subcommand> # 子命令详细帮助,如 secrets help add
|
||
|
||
# 添加或更新记录(upsert)
|
||
secrets add -n <namespace> --kind <kind> --name <name> \
|
||
[--tag <tag>]... # 可重复
|
||
[-m key=value]... # --meta 明文字段,-m 是短标志
|
||
[-s key=value]... # --secret 敏感字段,value 以 @ 开头表示从文件读取
|
||
|
||
# 搜索(默认隐藏 encrypted 内容)
|
||
secrets search [-n <namespace>] [--kind <kind>] [--tag <tag>] [-q <keyword>] [--show-secrets]
|
||
# -q 匹配范围:name、namespace、kind、metadata 全文内容、tags
|
||
|
||
# 开启 debug 级别日志(全局参数,位于子命令之前)
|
||
secrets --verbose <subcommand>
|
||
secrets -v <subcommand>
|
||
# 或通过环境变量控制:RUST_LOG=secrets=trace secrets search
|
||
|
||
# 增量更新已有记录(合并语义,记录不存在则报错)
|
||
secrets update -n <namespace> --kind <kind> --name <name> \
|
||
[--add-tag <tag>]... # 添加标签(不影响已有标签)
|
||
[--remove-tag <tag>]... # 移除标签
|
||
[-m key=value]... # 新增或覆盖 metadata 字段(不影响其他字段)
|
||
[--remove-meta <key>]... # 删除 metadata 字段
|
||
[-s key=value]... # 新增或覆盖 encrypted 字段(不影响其他字段)
|
||
[--remove-secret <key>]... # 删除 encrypted 字段
|
||
|
||
# 删除
|
||
secrets delete -n <namespace> --kind <kind> --name <name>
|
||
|
||
# 配置(持久化 database_url,设置一次即可)
|
||
secrets config set-db <url>
|
||
secrets config show
|
||
secrets config path
|
||
```
|
||
|
||
### 示例
|
||
|
||
```bash
|
||
# 添加服务器
|
||
secrets add -n refining --kind server --name i-uf63f2uookgs5uxmrdyc \
|
||
--tag aliyun --tag shanghai \
|
||
-m ip=47.117.131.22 -m desc="Aliyun Shanghai ECS" \
|
||
-s username=root -s ssh_key=@./keys/voson_shanghai_e.pem
|
||
|
||
# 添加服务凭据
|
||
secrets add -n refining --kind service --name gitea \
|
||
--tag gitea \
|
||
-m url=https://gitea.refining.dev \
|
||
-s token=<token>
|
||
|
||
# 搜索含 mqtt 的所有记录
|
||
secrets search -q mqtt
|
||
|
||
# 查看 refining 的全部服务配置(显示 secrets)
|
||
secrets search -n refining --kind service --show-secrets
|
||
|
||
# 按 tag 筛选
|
||
secrets search --tag hongkong
|
||
|
||
# 只更新一个 IP(不影响其他 metadata/secrets/tags)
|
||
secrets update -n refining --kind server --name i-uf63f2uookgs5uxmrdyc \
|
||
-m ip=10.0.0.1
|
||
|
||
# 给一条记录新增 tag 并轮换密码
|
||
secrets update -n refining --kind service --name gitea \
|
||
--add-tag production \
|
||
-s token=<new-token>
|
||
|
||
# 移除一个废弃的 metadata 字段
|
||
secrets update -n refining --kind service --name mqtt \
|
||
--remove-meta old_port
|
||
```
|
||
|
||
## 代码规范
|
||
|
||
- 错误处理:统一使用 `anyhow::Result`,不用 `unwrap()`
|
||
- 异步:全程 `tokio`,数据库操作 `sqlx` async
|
||
- SQL:使用 `sqlx::query` / `sqlx::query_as` 绑定参数,禁止字符串拼接(搜索的动态 WHERE 子句除外,需使用参数绑定 `$1/$2`)
|
||
- 新增 `kind` 类型时:只需在 `add` 调用时传入,无需改代码
|
||
- 字段命名:CLI 短标志 `-n`=namespace,`-m`=meta,`-s`=secret,`-q`=query,`-v`=verbose
|
||
- 日志:用户可见输出用 `println!`;调试/运维信息用 `tracing::debug!`/`info!`/`warn!`/`error!`
|
||
- 审计:`add`/`update`/`delete` 成功后调用 `audit::log()`,写入 `audit_log` 表;失败只 warn 不中断
|
||
|
||
## 提交前检查(必须全部通过)
|
||
|
||
每次提交代码前,请在本地依次执行以下检查,**全部通过后再 push**:
|
||
|
||
### 1. 版本号(按需)
|
||
|
||
若本次改动需要发版,请先确认 `Cargo.toml` 中的 `version` 已提升,避免 CI 打出的 Tag 与已有版本重复。可通过 git tag 判断:
|
||
|
||
```bash
|
||
# 查看当前 Cargo.toml 版本
|
||
grep '^version' Cargo.toml
|
||
|
||
# 查看是否已存在该版本对应的 tag(CI 使用格式 secrets-<version>)
|
||
git tag -l 'secrets-*'
|
||
```
|
||
|
||
若当前版本已被 tag(例如已有 `secrets-0.1.0` 且 `Cargo.toml` 仍为 `0.1.0`),则应在 `Cargo.toml` 中 bump 版本号后再提交,以便 CI 自动打新 Tag 并发布 Release。
|
||
|
||
### 2. 格式、Lint、测试
|
||
|
||
```bash
|
||
cargo fmt -- --check # 格式检查(不通过则运行 cargo fmt 修复)
|
||
cargo clippy -- -D warnings # Lint 检查(消除所有 warning)
|
||
cargo test # 单元/集成测试
|
||
```
|
||
|
||
或一次性执行:
|
||
|
||
```bash
|
||
cargo fmt -- --check && cargo clippy -- -D warnings && cargo test
|
||
```
|
||
|
||
## CI/CD
|
||
|
||
- Gitea Actions(runner: debian)
|
||
- 触发:`src/**`、`Cargo.toml`、`Cargo.lock` 变更推送到 main
|
||
- 构建目标:`x86_64-unknown-linux-musl`(静态链接,无 glibc 依赖)
|
||
- 新版本自动打 Tag(格式 `secrets-<version>`)并上传二进制到 Gitea Release
|
||
- 通知:飞书 Webhook(`vars.WEBHOOK_URL`)
|
||
- 所需 secrets/vars:`RELEASE_TOKEN`(Release 上传,Gitea PAT)、`vars.WEBHOOK_URL`(通知,可选)
|
||
|
||
## 环境变量
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `RUST_LOG` | 日志级别,如 `secrets=debug`、`secrets=trace`(默认 warn) |
|
||
| `USER` | 审计日志 actor 字段来源,Shell 自动设置,通常无需手动配置 |
|
||
|
||
数据库连接通过 `secrets config set-db` 持久化到 `~/.config/secrets/config.toml`,不支持环境变量。
|