P0: - fix(config): config_dir 使用 home_dir 回退,避免 ~ 不展开 - fix(search): 模糊查询转义 LIKE 通配符 % 和 _ P1: - chore(db): 连接池添加 acquire_timeout 10s - refactor(update): 消除 meta_keys/secret_keys 重复计算 P2: - refactor(config): 合并 ConfigAction 枚举 - chore(deps): 移除 clap/env、uuid/v4 无用 features - perf(main): delete 命令跳过 master_key 加载 - i18n(config): 统一错误消息为英文 - perf(search): show_secrets=false 时不再解密获取 key_count - feat(delete,update): 支持 -o json/json-compact 输出 P3: - feat(search): --tag 支持多值交叉过滤 docs: 将 seed-data.sh 替换为 setup-gitea-actions.sh Made-with: Cursor
9.0 KiB
secrets
跨设备密钥与配置管理 CLI,基于 Rust + PostgreSQL 18。
将服务器信息、服务凭据统一存入数据库,供本地工具和 AI 读取上下文。敏感数据(encrypted 字段)使用 AES-256-GCM 加密存储,主密钥由 Argon2id 从主密码派生并存入系统钥匙串。
安装
cargo build --release
# 或从 Release 页面下载预编译二进制
首次使用(每台设备各执行一次)
# 1. 配置数据库连接
secrets config set-db "postgres://postgres:<password>@<host>:<port>/secrets"
# 2. 初始化主密钥(提示输入主密码,派生后存入 OS 钥匙串)
secrets init
主密码不会存储,仅用于派生主密钥。同一主密码在所有设备上会得到相同主密钥(salt 存于数据库,首台设备生成后共享)。
主密钥存储:macOS → Keychain;Windows → Credential Manager;Linux → keyutils(会话级,重启后需再次 secrets init)。
从旧版(明文存储)升级:升级后首次运行需执行 secrets init 即可(明文记录需手动重新 add 或通过 update 更新)。
AI Agent 快速指南
这个 CLI 以 AI 使用优先设计。核心路径只有一条:读取用 search,写入用 add / update。
第一步:发现有哪些数据
# 列出所有记录摘要(默认最多 50 条,安全起步)
secrets search --summary --limit 20
# 按 namespace 过滤
secrets search -n refining --summary --limit 20
# 按最近更新排序
secrets search --sort updated --limit 10 --summary
--summary 只返回轻量字段(namespace、kind、name、tags、desc、updated_at),不含完整 metadata 和 secrets。
第二步:精确读取单条记录
# 精确定位(namespace + kind + name 三元组)
secrets search -n refining --kind service --name gitea
# 获取完整记录含 secrets(JSON 格式,AI 最易解析)
secrets search -n refining --kind service --name gitea -o json --show-secrets
# 直接提取单个字段值(最短路径)
secrets search -n refining --kind service --name gitea -f secret.token
secrets search -n refining --kind service --name gitea -f metadata.url
# 同时提取多个字段
secrets search -n refining --kind service --name gitea \
-f metadata.url -f metadata.default_org -f secret.token
-f secret.* 会自动解锁 secrets,无需额外加 --show-secrets。
输出格式
| 场景 | 推荐命令 |
|---|---|
| AI 解析 / 管道处理 | -o json 或 -o json-compact |
写入 .env 文件 |
-o env --show-secrets |
| 人类查看 | 默认 text(TTY 下自动启用) |
| 非 TTY(管道/重定向) | 自动 json-compact |
# 管道直接 jq 解析(非 TTY 自动 json-compact)
secrets search -n refining --kind service | jq '.[].name'
secrets search -n refining --kind service --name gitea --show-secrets | jq '.secrets.token'
# 导出为可 source 的 env 文件(单条记录)
secrets search -n refining --kind service --name gitea -o env --show-secrets \
> ~/.config/gitea/config.env
完整命令参考
# 查看帮助(包含各子命令 EXAMPLES)
secrets --help
secrets init --help # 主密钥初始化
secrets search --help
secrets add --help
secrets update --help
secrets delete --help
secrets config --help
# ── search ──────────────────────────────────────────────────────────────────
secrets search --summary --limit 20 # 发现概览
secrets search -n refining --kind service # 按 namespace + kind
secrets search -n refining --kind service --name gitea # 精确查找
secrets search -q mqtt # 关键词模糊搜索
secrets search --tag hongkong # 按 tag 过滤
secrets search -n refining --kind service --name gitea -f secret.token # 提取字段
secrets search -n refining --kind service --name gitea -o json --show-secrets # 完整 JSON
secrets search --sort updated --limit 10 --summary # 最近改动
secrets search -n refining --summary --limit 10 --offset 10 # 翻页
# ── add ──────────────────────────────────────────────────────────────────────
secrets add -n refining --kind server --name my-server \
--tag aliyun --tag shanghai \
-m ip=47.117.131.22 -m desc="Aliyun Shanghai ECS" \
-s username=root -s ssh_key=@./keys/server.pem
secrets add -n refining --kind service --name gitea \
--tag gitea \
-m url=https://gitea.refining.dev -m default_org=refining \
-s token=<token>
# ── update ───────────────────────────────────────────────────────────────────
secrets update -n refining --kind server --name my-server -m ip=10.0.0.1
secrets update -n refining --kind service --name gitea --add-tag production -s token=<new>
secrets update -n refining --kind service --name mqtt --remove-meta old_port --remove-secret old_key
# ── delete ───────────────────────────────────────────────────────────────────
secrets delete -n refining --kind service --name legacy-mqtt
# ── init ─────────────────────────────────────────────────────────────────────
secrets init # 主密钥初始化(每台设备一次,主密码派生后存钥匙串)
# ── config ───────────────────────────────────────────────────────────────────
secrets config set-db "postgres://postgres:<password>@<host>:<port>/secrets"
secrets config show # 密码脱敏展示
secrets config path # 打印配置文件路径
# ── 调试 ──────────────────────────────────────────────────────────────────────
secrets --verbose search -q mqtt
RUST_LOG=secrets=trace secrets search
数据模型
单张 secrets 表,首次连接自动建表;同时自动创建 audit_log 表,记录所有写操作。
| 字段 | 说明 |
|---|---|
namespace |
一级隔离,如 refining、ricnsmart |
kind |
记录类型,如 server、service(可自由扩展) |
name |
人类可读唯一标识 |
tags |
多维标签,如 ["aliyun","hongkong"] |
metadata |
明文描述信息(ip、desc、domains 等) |
encrypted |
敏感凭据(ssh_key、password、token 等),AES-256-GCM 加密存储 |
-m / --meta 写入 metadata,-s / --secret 写入 encrypted,value=@file 从文件读取内容。加解密使用主密钥(由 secrets init 设置)。
审计日志
add、update、delete 操作成功后自动向 audit_log 表写入一条记录,包含操作类型、操作对象和变更摘要(不含 secret 值)。操作者取自 $USER 环境变量。
-- 查看最近 20 条审计记录
SELECT action, namespace, kind, name, actor, detail, created_at
FROM audit_log
ORDER BY created_at DESC
LIMIT 20;
项目结构
src/
main.rs # CLI 入口(clap),含各子命令 after_help 示例
output.rs # OutputMode 枚举 + TTY 检测
config.rs # 配置读写(~/.config/secrets/config.toml)
db.rs # 连接池 + auto-migrate(secrets + audit_log + kv_config)
crypto.rs # AES-256-GCM 加解密、Argon2id 派生、OS 钥匙串
models.rs # Secret 结构体
audit.rs # 审计日志写入(audit_log 表)
commands/
init.rs # 主密钥初始化(首次/新设备)
add.rs # upsert,支持 -o json
config.rs # config set-db/show/path
search.rs # 多条件查询,支持 -f/-o/--summary/--limit/--offset/--sort
delete.rs # 删除
update.rs # 增量更新(合并 tags/metadata/encrypted)
scripts/
setup-gitea-actions.sh # 配置 Gitea Actions 变量与 Secrets
CI/CD(Gitea Actions)
推送 main 分支时自动:fmt/clippy 检查 → musl 构建 → 创建 Release 并上传二进制。
首次使用需配置 Actions 变量和 Secrets:
# 需有 ~/.config/gitea/config.env(GITEA_URL、GITEA_TOKEN、GITEA_WEBHOOK_URL)
./scripts/setup-gitea-actions.sh
RELEASE_TOKEN(Secret):Gitea PAT,用于创建 Release 上传二进制WEBHOOK_URL(Variable):飞书通知,可选
详见 AGENTS.md。