riptideslabs/keyledger

GitHub: riptideslabs/keyledger

一个用 Go 构建的终端仪表盘工具,提供跨多个 AI 供应商 API 密钥的统一清单、健康评分和快照差异追踪。

Stars: 24 | Forks: 0

# KeyLedger KeyLedger 是一个交互式终端仪表板,它为您提供跨 AI 供应商发布的每个 API key 的统一视图——包含健康评分、快照差异对比和加密凭证存储。 ![演示](https://raw.githubusercontent.com/riptideslabs/keyledger/main/docs/demos/demo.gif) ## 功能 - **交互式 TUI** — 使用 [Bubble Tea](https://github.com/charmbracelet/bubbletea) 构建的全屏终端仪表板 - **统一清单** — 在可配置的超时时间内同时查询您的所有 AI 供应商 - **健康评分** — 通过可配置的时长阈值标记过时、空闲或从未使用过的 key;在 key 视图中提供专用的且可排序的“风险”列 - **WorkSpaces 视图** — 每个供应商的层级式 workspace/project 树,包含每个作用域的 key 数量和风险明细,可作为 key 视图中的一个标签页访问 - **实时过滤** — 按名称、作用域、状态、时长、所有者、风险评分等条件搜索 key - **快照管理器** — 在专用的快照视图中列出、导出、删除和对快照进行差异对比;从 key 或健康视图触发快照 - **定期监控模式** — 按计划收集 key,持久化到数据库,并自动导出 JSON 文件 - **加密凭证存储** — 凭证存储在 AES-256-GCM 加密的 SQLite 中;磁盘上绝不会留存明文 - **供应商管理 UI** — 交互式地启用/禁用供应商并配置凭证;凭证状态显示为 "set" 或 "missing" ## 文档 供应商设置指南、配置参考和示例位于 [keyledger.riptides.io](https://keyledger.riptides.io/)。 ## 供应商覆盖范围 | 供应商 | Key 列出 | 所有者信息 | 最后使用 | |---|---|---|---| | OpenAI | ✓ | ✓ | ✓ | | Anthropic | ✓ | ✓ | ✓ (30 天窗口期) | | AWS IAM 访问 key | ✓ | ✓ | ✓ | | AWS 服务特定凭证 | ✓ | ✓ | — | | Google Cloud IAM | ✓ | — | — | | Mistral | ✓ | ✓ | ✓ | ## 安装说明 ### go install ``` go install github.com/riptideslabs/keyledger@latest ``` ### 从源码构建 ``` git clone https://github.com/riptideslabs/keyledger cd keyledger make build ./build/keyledger ``` ### 安装到 GOPATH/bin ``` make install ``` 需要 Go 1.25 或更高版本。不需要 CGO。 ## 配置 ### 凭证 启动 TUI 并按 **`p`** 打开供应商界面。选择一个供应商,启用它,然后输入您的 API 凭证——它们将存储在 AES-256-GCM 加密的 SQLite 数据库中,绝不会以明文形式写入磁盘。首次使用时,系统会提示您设置主密码。 ### OpenAI | 凭证字段 | 描述 | |---|---| | `admin_key` | 来自 platform.openai.com → API keys 的管理员 API key (`sk-admin-…`) | 此管理员 key 必须具有列出组织内所有 key 的权限。默认情况下会枚举所有 project;在供应商界面中使用 **排除项目** 可跳过特定项目。 ### Anthropic | 凭证字段 | 描述 | |---|---| | `admin_key` | 来自 console.anthropic.com → API Keys 的管理员 API key (`sk-ant-admin01-…`) | 此管理员 key 必须属于具有 **管理员** 角色的账户。可选设置(解析用户/workspace 名称、排除 workspace)可在供应商界面中进行配置。 ### AWS 支持三种凭证模式,按以下顺序尝试: | 模式 | 凭证字段 | 描述 | |---|---|---| | SSO profile | `sso_creds` | 执行 `aws sso login` 后 `~/.aws/config` 中的配置文件名称 | | 静态 key | `access_key_id` + `secret_access_key` | 长期有效的 IAM 访问 key | 必须单独设置 `sso_creds`,或者同时设置 `access_key_id` **和** `secret_access_key` —— 当存在最少必填字段时,供应商界面会显示 **已设置**。 ### Google Cloud | 凭证字段 | 描述 | |---|---| | `service_account_json` | GCP 服务账号 key 文件的完整 JSON 内容 | 将下载的 `.json` key 文件的全部内容粘贴到 `service_account_json` 字段中。该服务账号需要以下角色(或等效的自定义权限): - `roles/resourcemanager.projectViewer` — 用于枚举项目 - `roles/apikeys.viewer` — 用于列出 API key - `roles/iam.serviceAccountViewer` — 用于列出服务账号 key 默认情况下,会自动发现所有可访问的项目。使用 **项目 (覆盖)** 可固定一组 project ID 列表,或使用 **排除项目** 跳过特定项目。 ### Mistral Mistral 使用交互式登录流程,而不是静态 API key。在供应商界面中按 **登录** 并输入您的 Mistral 电子邮件和密码 —— keyledger 会通过 Mistral 的 Kratos endpoint 进行身份验证并自动存储 session token。每次登录时都会刷新 session token。 ## 用法 ### 交互式 TUI ``` keyledger ``` 启动全屏仪表板。所有状态(已启用的供应商、设置、快照)都会持久化到 `~/.keyledger/keyledger.db`。 ### 键盘快捷键 | 按键 | 操作 | |---|---| | `1` | key 视图 | | `2` | 健康视图 | | `3` | 差异视图 | | `4` | 快照视图 | | `p` | 供应商管理 | | `g` | 设置 | | `r` | 刷新所有供应商 | | `s` | 将快照保存到数据库(key / 健康视图) | | `tab` | 切换侧边栏焦点 | | `o` | 循环排序方式(key 视图) | | `← →` | 在 key 和 WorkSpaces 标签页之间切换(key 视图) | | `/` | 过滤 key(key 视图) | | `?` | 切换帮助覆盖层 | | `esc` | 返回 / 关闭对话框 | | `q` | 退出 | #### key 视图列 key 表格在状态列旁边包含一个专用的 **风险** 列(`ok` / `WARN` / `CRIT`),因此您无需打开健康视图即可一目了然地查看健康状况。当前处于激活状态的排序列会以紫色和下划线高亮显示。排序循环依次为:创建时间 → 最后使用 → 名称 → 风险。 #### key 视图过滤语法 | 表达式 | 匹配 | |---|---| | `foo` | ID、名称、作用域或状态中的子字符串 | | `name:prod` | 名称包含 "prod" 的 key | | `scope:staging` | 作用域包含 "staging" 的 key | | `status:active` | 状态完全为 "active" 的 key | | `risk:critical` | 风险评分为 "critical" 的 key | | `age:>90` | 超过 90 天的 key | | `idle:never` | 从未使用过的 key | | `owner:alice` | 由匹配 "alice" 的用户创建的 key | ### 监控模式 ``` keyledger watch [--interval ] [--output ] [--unseal-addr ] keyledger --data-dir /mnt/data watch --interval 1h ``` 持续运行:收集 key,保存到数据库,并在每次触发 (tick) 时导出一个 JSON 文件。遇到 `Ctrl+C` 或 `SIGTERM` 时会干净地停止。 ``` keyledger watch --interval 1h --output /var/log/keyledger ``` 每次运行都会打印一行摘要: ``` [2026-05-11 03:00:00] snapshot #12 — 47 keys (0 critical, 2 warnings) → /var/log/keyledger/snapshot-20260511T030000.json ``` `--interval` 标志接受任何 Go duration 字符串:`30m`、`1h`、`6h`、`24h` 等。默认为 `1h`。 `--output` 设置快照 JSON 文件的写入位置。数据库独立存在 —— 使用 `--data-dir`(或 `$KEYLEDGER_HOME`)将其指向其他位置;启动日志行 `watch: store: …` 始终会显示当前哪个数据库处于活动状态。 #### Unseal API (无头模式 / Docker) 在无头环境(例如,没有终端的 Linux 容器)中,`watch` 会自动启动一个本地 HTTPS API,以便在运行时提供凭证。 ``` watch: credential store locked — POST password to https://127.0.0.1:9876/v1/unseal watch: TLS cert fingerprint (SHA-256): AB:CD:EF:… ``` 服务器使用临时的自签名 TLS 证书(ECDSA P-256,有效期 24 小时)。使用 `--unseal-addr` 更改绑定地址(默认为 `127.0.0.1:9876`)。 | Endpoint | 方法 | Body | 描述 | |---|---|---|---| | `/v1/status` | GET | — | `{"sealed":bool,"setup":bool}` | | `/v1/providers` | GET | — | 列出已注册的供应商及其预期的字段名称 | | `/v1/init` | POST | `{"password":"…"}` | 在首次运行时初始化加密,然后解封 | | `/v1/unseal` | POST | `{"password":"…"}` | 解封已初始化的存储 | | `/v1/credentials` | POST | `{"provider":"…","field":"…","value":"…"}` | 存储凭证并启用该供应商(需要处于解封状态) | | `/v1/credentials` | DELETE | `{"provider":"…","field":"…"}` | 移除凭证(需要处于解封状态) | 在提交凭证之前,使用 `GET /v1/providers` 发现确切的字段名称: ``` curl -sk https://localhost:9876/v1/providers # [ # {"provider":"anthropic","fields":["admin_key"]}, # {"provider":"aws","fields":["access_key_id","secret_access_key","sso_creds"]}, # {"provider":"google","fields":["service_account_json"]}, # {"provider":"openai","fields":["admin_key"]} # ] ``` ### Docker 每次发布时,都会将预构建的多架构镜像(linux/amd64、linux/arm64)发布到 GitHub Container Registry: ``` docker pull ghcr.io/riptideslabs/keyledger:latest docker run -p 9876:9876 -v keyledger-data:/data ghcr.io/riptideslabs/keyledger:latest ``` 或者从源码在本地构建: ``` docker build -t keyledger . docker run -p 9876:9876 -v keyledger-data:/data keyledger ``` 默认情况下,容器运行 `keyledger watch --unseal-addr 0.0.0.0:9876 --interval 5m`。使用 unseal API 提供凭证: ``` # 1. 检查加密是否已经初始化 curl -sk https://localhost:9876/v1/status # {"sealed":true,"setup":false} # 2a. 首次运行 —— 初始化加密并一步解封 curl -sk -X POST https://localhost:9876/v1/init \ -H 'Content-Type: application/json' \ -d '{"password":"my-secret"}' # {"sealed":false} # 2b. 后续重启 —— 存储已初始化,只需解封 curl -sk -X POST https://localhost:9876/v1/unseal \ -H 'Content-Type: application/json' \ -d '{"password":"my-secret"}' # 3. 推送 provider 凭据 curl -sk -X POST https://localhost:9876/v1/credentials \ -H 'Content-Type: application/json' \ -d '{"provider":"openai","field":"admin_key","value":"sk-..."}' curl -sk -X POST https://localhost:9876/v1/credentials \ -H 'Content-Type: application/json' \ -d '{"provider":"anthropic","field":"admin_key","value":"sk-ant-..."}' # 移除凭据 curl -sk -X DELETE https://localhost:9876/v1/credentials \ -H 'Content-Type: application/json' \ -d '{"provider":"openai","field":"admin_key"}' ``` ## 开发 ``` make help # list all targets make build # build for current platform make build-all # cross-compile for all platforms make run # build and launch the TUI make test # run tests with coverage make lint # run golangci-lint (downloads on first run) make lint-fix # run golangci-lint with auto-fix make check # fmt + vet + lint make clean # remove build artifacts ``` ## 许可证 MIT — 见 [LICENSE](LICENSE)。版权所有 © 2026 Riptides Labs, Inc.
标签:EVTX分析, 日志审计, 请求拦截