Skip to main content
Glama
CredVault

CredVault

by CodeCoreLab

CredVault

CI License: MIT Python deps tests

AI 主用、人工辅助的凭据平台。 给 AI 的是「任务级能力」,不是「一把能读所有密码的钥匙」: 凭据只在内核里出现一次,AI 永远拿到脱敏后的结果;人只在审批 / 审计 / 令牌三处出现。

AI 客户端 ──MCP(stdio/HTTP+Bearer)──> 能力注册表 ──> 策略 ──> 审批 ──> 注入 ──> 脱敏 ──> 哈希链审计
                                        ▲                                      │
                                    capabilities/*.yaml(加一行=多一个工具)     └──> 脱敏后的结构化结果

为什么是这个形态(而不是又一个密码管理器)

个人密码管理器解决「人记不住密码」;桌面 AI 金库(如 Sigil 掌玺)解决「AI 别拿到明文」, 但要求桌面端常开且已解锁,服务器场景不成立。CredVault 解决的是第三个问题: 在无人值守的服务器上,让 AI 用得对、用得省、出问题查得到。

判据

本项目的做法

AI 能不能自己发现「能做什么」

initialize.instructions 动态生成中文引导 + list_capabilities 自省;未授权的能力不出现在工具列表里

调用是不是任务语义

工具名是 zabbix_host_list,不是 call_api(credential, url, method) —— AI 不用知道 URL 形态

会不会烧掉上下文

返回体默认 32KB 硬预算 + summary_only 结构化裁剪 + structuredContent

失败了能不能自愈

20 个错误码(0/10–20)+ next_action,instructions 里写明每种码该怎么处置

需审批会不会卡死

异步审批:返回 approval_id → 人点 Web/企微 → AI 轮询 approval_status 后重试;支持会话豁免

人要不要会命令行

不用。审批在 Web 三视图里点,事件可推企微

Related MCP server: AgentGate

5 分钟上手

# 1) 安装(幂等:重复执行不覆盖数据)
./install.sh                        # 数据目录默认 ~/.credvault
export CREDVAULT_HOME=~/.credvault

# 2) 录一条凭据(值不回显;kind 决定必填字段与形态校验)
credvault cred set ZABBIX_TOKEN --kind api_token --value-stdin < /dev/stdin

# 3) 签一个 AI 令牌(明文只显示一次)
credvault token add workbuddy-local --ttl-days 90

# 4) 接进 MCP 客户端
#    {"mcpServers":{"credvault":{"command":"credvault","args":["mcp"],
#      "env":{"CREDVAULT_TOKEN":"cbk_..."}}}}

# 5) 起 Web(审批/审计/令牌三视图)
credvault user add admin
credvault serve --mode web          # http://127.0.0.1:8443

自检与验证:

credvault doctor                     # 8 项探针:策略/能力/凭据/密文/KEK/审计链/开关/到期
credvault policy-check               # 逐条列出授权,防「以为放开了其实没有」
credvault invoke zabbix_host_list --agent workbuddy-local --explain   # 干跑,不发起真实调用
credvault audit verify               # 哈希链完整性

两条程序入口:MCP 与 REST API

同一套六道闸门、同一个 dispatch,只是入口与鉴权方式不同。令牌带 scope,两条路互不越界:

scope

MCP(stdio / HTTP /mcp)

REST API(/api/v1/*)

mcp(默认)

✅

❌ 403

api

❌ 403

✅

both

✅

✅

默认 mcp 而不是 both:升级不扩权——已有令牌不会因为升级而顺带获得脚本调用能力。 存量库升级时 agents.scope 自动补成 mcp(同上原则)。

MCP(给 AI 客户端)

{"mcpServers":{"credvault":{"command":"credvault","args":["mcp"],
  "env":{"CREDVAULT_TOKEN":"cbk_..."}}}}

HTTP 形态:POST /mcp,Authorization: Bearer cbk_...。工具清单按双轴授权渐进披露, 未授权的能力不会出现在 tools/list 里。

REST API(给脚本 / CI / 监控探针)

credvault token add ci-probe --ttl-days 30 --scope api      # 特意签发 api 专用令牌

export CV=http://127.0.0.1:8443/api/v1
export T="Authorization: Bearer cbk_..."

curl -H "$T" $CV/whoami                       # 我是谁、能调什么、还剩多少额度
curl -H "$T" $CV/capabilities                 # 能力清单(含约束与配额)
curl -H "$T" $CV/credentials                  # 凭据元数据(永不返回值)
curl -H "$T" "$CV/audit?hours=24&limit=50"    # 审计检索
curl -H "$T" $CV/health                       # 平台自检

# 干跑:不发真实请求,先看判定
curl -X POST -H "$T" -H 'Content-Type: application/json' \
     -d '{"capability":"zabbix_host_list","args":{"limit":5}}' $CV/explain

# 真实调用
curl -X POST -H "$T" -H 'Content-Type: application/json' \
     -d '{"capability":"zabbix_host_list","args":{"limit":5}}' $CV/invoke

# 需审批的写操作:返回 202 + approval_id,人工批准后带上它重试
curl -X POST -H "$T" -H 'Content-Type: application/json' \
     -d '{"capability":"wecom_send_text","args":{"content":"x"}}' $CV/invoke
# → 202 {"code":11,"approval_id":"..."}   ← 人点 Web 审批 → 重试同一请求并附 approval_id

接口描述:GET /api/openapi.json(OpenAPI 3.1,公开文档,不含任何凭据信息)。

HTTP 状态码与业务码分离——脚本可按状态码写重试逻辑,按 code 写业务分支:

HTTP

含义

对应 code

200

成功 / 业务失败(读 code 再判断)

0、15、20

202

已受理待审批(不是错误)

11

400

参数非法

16

401

令牌无效/过期/吊销/IP 不符

4010

403

scope 不符 / 策略拒绝 / 安全拦截

4011、10、12

404

凭据不可用

13

429

超出配额

18

502

上游网络失败

14

503

Kill Switch 只读

19

三条硬边界(不因为是「API」而放松):

  1. 没有读凭据值的接口。取明文只有 lease pull(带 TTL、可撤销、只出现一次)

  2. API 只认 Bearer 令牌,不认 Web 会话 Cookie;反之 /mcp 也不认 Cookie

  3. 所有调用进哈希链审计,actor=api:<agent>,参数摘要先脱敏再落盘

写一个能力(加一段 YAML = 多一个 AI 工具)

version: 1
capabilities:
  - name: zabbix_host_list                # ^[a-z][a-z0-9_]{2,60}$
    kind: http                            # http | exec | rotate
    description: 列出 Zabbix 主机(只读)。用于晨检与资产盘点。   # 必填,AI 靠它选工具
    read_only: true                       # Kill Switch 期间只读能力仍放行
    require_confirm: false                # 写操作建议 true
    secret_ref: ZABBIX_TOKEN              # 只写名字,值由内核注入
    input_schema:                         # JSON Schema 子集,错参数当场拒
      type: object
      properties:
        filter: {type: string, maxLength: 64}
        limit:  {type: integer, default: 50, minimum: 1, maximum: 500}
    http:
      method: POST                        # 固定方法,不接受调用方改写
      base_url: https://zabbix.example.com
      path: /api_jsonrpc.php              # 固定路径,可含 {{ 变量 }}
      inject: {type: header, name: Authorization, prefix: "Bearer "}
      allow_private_upstream: true        # 内网地址需显式开启(默认禁)
      body_template:
        jsonrpc: "2.0"
        method: host.get
        params: {output: [hostid, host], search: {host: "{{ filter | default('') }}"}}
        id: 1
    response: {json: true, pick: result, array_limit: 50}   # 结构化裁剪,省 token

不支持把 method / path 交给调用方拼:那等于又回到「URL 白名单代理」, 放行 /api_jsonrpc.php 之后 AI 仍能发 host.delete —— 只有把动作固化成能力,最小权限才成立。

kind: exec 需要 argv(列表,不接受 shell 字符串)+ env_var + argv_allowlist; kind: rotate 需要 rotate.credential 且必须 read_only: false + require_confirm: true。

授权策略

version: 1
defaults: {deny_by_default: true, quota_per_min: 60, quota_per_day: 2000}
deny:                                  # deny 永远优先于 allow
  - {capability: "*delete*", reason: 不可逆动作走人工}
agents:
  - id: workbuddy-local
    allow_exec: false                  # exec 注入默认关闭(第二把锁在 exec.enabled)
    visible_credentials: [ZABBIX_TOKEN] # 双轴之一:连「能看见哪些凭据名」都受限
    capabilities:
      - {name: zabbix_host_list, allow: true}
      - {name: wecom_send_text, allow: true, require_approval: true}
      - {name: "*", allow: false}

铁律:未显式 allow 一律拒 / deny 优先 / 未知字段直接报错(拼错 deny 不会静默放开)/ 最具体规则胜出(与书写顺序无关)。

审批闭环(AI 视角三步,人只需点一下)

  1. AI 调写能力 → 得到 {"code":11,"approval_id":"6afd7fde","next_action":...}

  2. 人收到企微通知或打开 Web「待审批」→ 批准(可勾「会话豁免」,同类本会话不再问)

  3. AI 调 approval_status("6afd7fde") 看到 approved → 带同一个 approval_id 重试原参数 (参数一改即失效,防「批准 A 执行 B」)

部署形态

形态

命令

说明

源码/venv

./install.sh

依赖只有 cryptography + pyyaml

单目录可执行

./build.sh binary

PyInstaller onedir,解压即跑,无需 Python

容器

docker build -t credvault .

非 root(uid 10001),/data 卷,内置 healthcheck

systemd

./install.sh --systemd

ProtectSystem=strict + 专用账号 + ReadWritePaths 只开数据目录

离线

./build.sh wheel && ./install.sh --offline dist/wheels

air-gap 可装

升级:替换程序 → credvault doctor → 数据自动向前迁移;升级前先 credvault backup export。 回滚:程序回退一版即可,数据层只增字段不删字段。

安全模型(能做与不能做)

做得到的

  • 信封加密:KEK(file 0600 / env)→ 每凭据独立 DEK → AES-256-GCM;KEK 轮换只重包 DEK(keys rewrap),不重加密数据

  • 凭据可用性闸门:过期 / 状态非 active / 凭据侧白名单不含本能力 → 调用与干跑同源拒绝(service._credential_gate)

  • 软限流(litellm 模式,默认关):超配额按 throttle_pct 概率放行、其余降速;burst 档永不降速,每次现算不复利

  • 参数级策略:constraints.arg_limits 对 max / max_len / pattern / enum 做逐参数收窄(warden 模式)

  • on-behalf-of 归属:审计记「agent 替谁办事」;仅策略显式 impersonate: true 且形如 human:* 才接受,MCP 侧默认丢弃

  • lease 化分发:lease issue/pull/renew/revoke,默认 300s、最长 3600s、续期 ≤3 次,值只在 pull 时出现一次

  • SSRF 与连接同源:解析一次即固定 IP 建连(Host 头保留域名),消除 DNS rebinding 窗口

  • 元数据与密文分库:拖走 credvault.db 拿不到密文;拖走 secrets.db 没有 KEK 也解不开

  • 明文生命周期限于单次调用(finally 清理);响应脱敏覆盖原值/URL 编码/JSON 转义/base64 三种形态

  • 审计哈希链:改任何一行即断链,audit verify 与 Web「链完整性」都会暴露

  • 双轴令牌 + IP 白名单 + TTL/轮换/吊销;令牌只存 sha256

  • SSRF:解析全部 A/AAAA,任一落私网即拒(不只看字面 IP);不跟随重定向

  • 非幂等方法不重试;连接池有上限;exec 走 argv 白名单 + 环境最小化

做不到的(不吹)

  • 客户端拿到脱敏结果后怎么用,平台看不到 —— 审计是事后可追溯,不是实时阻断

  • 全自动改所有上游密码:平台不知道每个系统的改密方式,轮换只做「生成 → 落库 → 探针验证 → 失败回滚」,远端投放由能力完成

  • 防住已有 root 的攻击者:他能读 KEK 文件。此形态定位是单机/单容器,不是多租户 SaaS

可移植性硬指标(15 条)

#

指标

落点

1

单产物 / 解压即用

build.sh + install.sh

2

零外部中间件(无 Redis/MySQL/JVM/Node)

SQLite + 标准库 HTTP

3

离线可装

install.sh --offline

4

配置全外置、代码零硬编码路径

config.py(CREDVAULT_HOME + 环境变量覆盖)

5

状态与运行身份解耦

所有路径锚定 HOME,不再探测 /opt/...

6

可升级/可回滚

数据层只增字段;升级前备份

7

可观测

/healthz /readyz /version /metrics(Prometheus)+ JSONL 审计

8

单端口

Web 与 MCP-over-HTTP 复用同一端口

9

无外呼

审计 sink 与审批通知默认 none,显式配置才外发

10

最小权限

KEK/库/history 均 600(Windows 走 icacls)

11

幂等部署

install.sh 可重复执行,不覆盖已有 KEK/库/策略

11b

运行时自省

credvault whoami / MCP whoami:可用能力+约束+剩余额度+Kill Switch

12

跨平台

Linux 主 / Windows 次(编码按 gb18030 兜底)

13

体积

onedir 约 40–60MB(Python 运行时的物理下限)

14

UTF-8 内部 + 本地编码出口

子进程输出显式 encoding + errors=replace

15

时间统一

存储 epoch/UTC,展示按 timezone

测试

python -m unittest discover -s tests -v     # 109 个用例,全绿

覆盖:配置合并与环境覆盖、信封加密/错钥/重包、密文与元数据分离、脱敏三形态、审计链篡改检测、 策略四条铁律、注册表校验与模板渲染、双轴令牌/IP 白名单、审批状态机与指纹绑定、配额与突发、 Kill Switch、exec 白名单、轮换探针失败回滚、备份包往返、MCP 握手/渐进披露/isError、Web 登录/角色/CSRF、 凭据到期/状态/凭据侧白名单、审批原子核销、审计参数摘要、config 配额优先级、软限流与 burst 豁免、 登录限速与 Cookie Secure、参数级约束、on-behalf-of、lease 生命周期/IP 白名单/续期上限、whoami 自省、 连接池按超时隔离、SSRF 同源解析、弱 KEK 体检、审批并发核销(16 线程)、 审计链并发追加(8×5)、配额窗口翻转、lease 过期清理、 sqlite 跨线程串行化(_LockedConn:execute/commit 复合操作互斥)。

目录

credvault/
├── credvault/            # 包(24 个模块,见下)
│   ├── config.py         # 配置外置 + 路径锚定
│   ├── crypto.py         # KEK→DEK 信封加密
│   ├── store.py          # 元数据库 / 密文库(分离)
│   ├── kinds.py          # 凭据类型注册表(必填字段 + 形态校验)
│   ├── registry.py       # 能力注册表(YAML → 工具 + 参数校验 + 模板)
│   ├── policy.py         # 能力级授权(deny-by-default / deny 优先)
│   ├── approvals.py      # 异步审批 + 会话豁免 + 通知
│   ├── tokens.py         # 双轴令牌 + IP + TTL
│   ├── executor.py       # HTTP 代发 / 子进程注入(SSRF、白名单、池上限)
│   ├── redact.py         # 脱敏 + 返回体预算
│   ├── audit.py          # 哈希链审计
│   ├── rotate.py         # 轮换(探针 + 回滚)
│   ├── service.py        # 装配 + 公开面(闸门/配额/执行委托)
│   ├── gates.py          # 闸门链(static→policy→credential→quota→approval)
│   ├── quota.py          # 配额 + 软限流(config>policy>默认)
│   ├── runner.py         # 执行器(唯一明文边界:解出→注入→脱敏)
│   ├── cli/              # 命令行:_common/lifecycle/health/creds/access/parser
│   ├── mcp.py            # MCP 服务(手写 JSON-RPC,不依赖 SDK)
│   ├── web.py            # 路由 + 登录 + 探针 + MCP-over-HTTP
│   ├── webui.py          # 三视图 HTML 渲染(纯函数)
│   ├── dist.py           # lease 化凭据分发
│   ├── backup.py         # .cvault 备份包
│   ├── ops.py            # 自检 / 指标
│   └── cli.py            # 命令行
├── capabilities/         # 能力定义(加 YAML 即加工具)
├── deploy/               # systemd 单元 + 环境投影示例
├── tests/                # 109 个用例
└── pyproject.toml       # 打包元数据(extras 预留)

明确不做

多租户与套餐、全功能管理后台、仪表盘报表、会话录屏、资产录屏级审计、OAuth 授权服务器、 自研 HSM —— 与「凭据底座」正交,做进来只会让交付物变重、责任面变大。

许可

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to make authenticated API calls and run commands with secrets injected, while keeping credentials completely hidden from the model, with policy enforcement, grants, and audit logging.
      6
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to call external endpoints under per-endpoint policy enforcement, with credentials and personal data kept inside a hardware enclave and every allowed or denied attempt recorded to an immutable audit ledger.
      2
      ISC
    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables AI agents to invoke upstream APIs without ever holding reusable credentials, using short-lived scoped capabilities and server-side secret injection. Also provides execution controls and x402 facilitator routing for secure agent actions.
      Apache 2.0
    • F
      license
      B
      quality
      A
      maintenance
      Enables AI agents to list, describe, and invoke scoped capabilities so they can perform brokered HTTP or SSH operations without ever receiving the underlying credential. All uses are deny-by-default, revocable, expiring, and recorded in a hash-chained audit log.
      3
      1
      -