panduraju50/zero-trust-boundary-vault-cli

GitHub: panduraju50/zero-trust-boundary-vault-cli

该工具是一个零信任生产环境访问 CLI,通过整合 OIDC、HashiCorp Vault 和 Boundary 三层门控,实现基于短时动态凭证的安全代理会话,消除静态密钥风险。

Stars: 0 | Forks: 0

# zero-trust-boundary-vault-cli (`ztb`) [![Rust](https://img.shields.io/badge/Rust-1.74%2B-000000?logo=rust&logoColor=white)](https://www.rust-lang.org/) [![HashiCorp Vault](https://img.shields.io/badge/HashiCorp-Vault-FFEC6E?logo=vault&logoColor=black)](https://www.vaultproject.io/) [![HashiCorp Boundary](https://img.shields.io/badge/HashiCorp-Boundary-F24C53?logo=hashicorp&logoColor=white)](https://www.boundaryproject.io/) [![OIDC](https://img.shields.io/badge/Auth-OIDC%20%2B%20PKCE-2F5BB7?logo=openid&logoColor=white)](https://openid.net/connect/) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE) ## 问题陈述 大多数进入生产环境的事故都源于一开始就不应该存在的凭证:`.env` 文件中长期的数据库密码、超出人员使用需求的个人 SSH 密钥、被粘贴到操作手册中的云访问密钥。**长期存在的静态凭证是生产运维中最大的可避免攻击面。** 它们可能会被窃取,很少能按时轮换,难以进行归因,并且单个泄露的凭证所授予的权限往往远超当前任务所需。 更安全的模型是**零信任、即时、代理访问**: - **默认不信任任何事物。** 每次访问请求都会针对企业身份提供商 (OIDC) 重新证明操作者*是谁*,而不是依赖于对密钥的持有。 - **凭证按需生成并迅速失效。** Vault 会签发一个具有短 TTL 的*动态* secret,以取代静态密码,并在任务结束时在源头将其撤销。 - **操作者永远不会直接路由到目标。** HashiCorp Boundary 负责代理会话:目标的网络位置永远不会暴露,并且连接可以被集中授权、限制时间以及取消。 这也提供了一个清晰的**气隙 / 破窗**方案。生产目标位于 Boundary worker 之后,没有来自操作者网络的入站路径;唯一的进入方式是获得新授权、完全审计且短暂的会话,该会话携带一分钟前不存在、一分钟后也将不存在的凭证。 `ztb` 是一个单一的 Rust CLI,它将这三层缝合在一个命令中,因此操作者的*简单*路径同时也是*安全*的路径。 ## 威胁模型 / 安全模型 ### 这可以防御什么 | 威胁 | 缓解措施 | | --- | --- | | **凭证窃取 / 泄露** | 没有可窃取的静态 secret。凭证是动态的、短 TTL 的,并在拆除时撤销。token 存储在 OS keyring 中,从不存储在磁盘或日志中。 | | **静态 / 过度访问** | 每次访问都需要实时的 OIDC 登录;Vault 角色遵循最小权限原则;Boundary 会话有时间限制且可集中撤销。 | | **横向移动** | Boundary 仅将会话代理给特定授权的目标;操作者没有通往更广网络的路由,也没有可用来进行跳板攻击的可重用凭证。 | | **授权码拦截** | 带有 **PKCE** (S256) 的 OIDC Authorization Code 流;CLI 是一个公共客户端,没有可泄露的 client secret。 | | **OIDC 回调上的 CSRF** | 在环回重定向上验证随机的 `state` 参数。 | | **ID token 重放** | 请求中嵌入随机 `nonce` 并在返回的 ID token 中进行验证;根据签发者的 JWKS 验证签名和标准声明。 | | **中间人攻击** | 始终强制执行 TLS 验证;Vault CA 通过配置进行固定。 | | **事后归因缺口** | 每一层都会发出审计事件 —— IdP 登录、Vault lease 签发、Boundary 会话授权 —— 并以相同的已验证身份为键。 | ### 多层门控 只有在 **所有三个** 独立层按顺序成功时,才会授予访问权限。任何一层的失败都会拒绝会话;没有回退到较弱路径的机制。 - **第 1 层 —— 身份 (OIDC)。** 操作者通过 Authorization Code + PKCE 针对企业 IdP(例如 Google Workspace)进行身份验证。返回的 ID token 会被验证(通过 JWKS 验证签名、`iss`、`aud`、`exp`、`nonce`)。这确立了*谁*在进行请求。Group/claim 成员资格驱动下游的所有操作。 - **第 2 层 —— 凭证门控。** 已验证的 OIDC token 通过 JWT/OIDC auth method 登录到 Vault,将身份映射到**最小权限的 Vault 角色**上。该角色授权从 secrets engine 请求*动态* secret(数据库、SSH、云、PKI),并按需签发且具有短 TTL 和硬性 `max_ttl`。不存在处于静态、容易被攻破的 secret。 - **第 3 层 —— 会话代理。** 相同的身份向 Boundary controller 进行身份验证,后者授权到特定目标的会话。Boundary worker 将连接代理到**仅限环回**的本地代理。在支持的情况下,Vault 签发的凭证会作为会话的代理凭证注入,因此操作者永远不会直接处理 secret。 ### 原则 - **最小权限** —— Vault 角色和 Boundary 目标根据已验证的身份声明,授予完成任务所需的最小范围权限。 - **短 TTL** —— 凭证的生命周期以分钟为单位,并在服务端设有上限。 - **磁盘上无 secret** —— token 进入 OS keyring;没有任何敏感信息被写入文件、环境变量或日志。 - **显式拆除** —— `logout`/退出会话会主动撤销 lease 并取消会话,这建立在自动 TTL 过期的基础之上(纵深防御)。 - **可审计性** —— 相同的已验证身份贯穿每一层。 ## 架构 ``` ztb connect ┌────────┐ │ │Operator│ ▼ └───┬────┘ ┌───────────────────┐ │ local loopback proxy │ ztb CLI │ │ (127.0.0.1 only) │ (Rust, clap) │ │◄────────────────────────────┤ │ │ └─────────┬─────────┘ │ │ │ Layer 1: OIDC (Auth Code + PKCE, state + nonce) │ ▼ │ ┌───────────────────────┐ │ │ OIDC IdP │ ID/access token │ │ (Google Workspace) │ TTL ~1h, in keyring │ └───────────┬───────────┘ │ │ verified access token │ Layer 2: Vault JWT/OIDC login ▼ │ ┌───────────────────────┐ │ │ HashiCorp Vault │ dynamic secret │ │ role: least-priv │ TTL ~15m (max_ttl) │ │ engine: db/ssh/pki │ leased, revocable │ └───────────┬───────────┘ │ │ short-lived credential │ Layer 3: authorize + broker ▼ │ ┌───────────────────────┐ │ │ HashiCorp Boundary │ session │ │ controller + worker │ time-boxed, │ │ cred injection │ cancelable │ └───────────┬───────────┘ │ │ brokered session │ ▼ │ ┌───────────────────────┐ └──────────────────────────►│ Target host / DB │ (air-gapped; (proxied through worker) │ (no direct route) │ no inbound path) └───────────────────────┘ Lifetimes (illustrative; enforced server-side): OIDC access token ...... ~1h, cached in OS keyring, never on disk Vault dynamic secret ... ~15m, hard max_ttl, revoked on teardown Boundary session ....... time-boxed by target config, centrally cancelable ``` ## CLI 用法 ``` ztb [OPTIONS] ``` ### 命令 | 命令 | 描述 | | --- | --- | | `ztb login` | 通过 OIDC(Authorization Code + PKCE)进行身份验证;将 token 缓存在 OS keyring 中。 | | `ztb connect ` | 重新验证身份,请求短暂的 Vault 凭证,并代理到 `` 的 Boundary 会话。 | | `ztb status` | 显示当前身份、凭证 TTL 和活动会话。 | | `ztb whoami` | 从缓存的 OIDC token 中打印身份(subject/email)。 | | `ztb logout` | 撤销 Vault lease,取消 Boundary 会话,并清除 keyring。 | ### 全局选项 | 标志 | 环境变量 | 描述 | | --- | --- | --- | | `--vault-addr ` | `VAULT_ADDR` | HashiCorp Vault 地址。 | | `--boundary-addr ` | `BOUNDARY_ADDR` | Boundary controller 地址。 | | `--oidc-issuer ` | `ZTB_OIDC_ISSUER` | OIDC 签发者 URL。 | | `--ttl ` | — | 请求的凭证 TTL(例如 `15m`);受 Vault 角色上限限制。 | | `--json` | — | 输出机器可读的 JSON。 | | `-v`, `-vv` | `RUST_LOG` | 增加日志详细程度。 | ### 示例 ``` # 1) 登录到企业 IdP(打开浏览器;PKCE loopback flow)。 ztb login \ --oidc-issuer https://accounts.google.com \ --client-id ztb-cli.apps.googleusercontent.com # 2) 向生产数据库目标代理一个 10 分钟的会话。 ztb connect prod/orders-db-readonly \ --vault-addr https://vault.internal:8200 \ --boundary-addr https://boundary.internal:9200 \ --ttl 10m # 3) 以 JSON 格式检查当前状态(例如用于工具 / 仪表板)。 ztb status --json # 4) 根据缓存的 token,我是谁? ztb whoami # 5) 销毁一切:撤销 leases、取消会话、清除 keyring。 ztb logout ``` ## 配置 `ztb` 按优先级从低到高的顺序读取配置: 1. `~/.config/ztb/config.toml` 2. 环境变量 3. 命令行标志 查看 [`config.example.toml`](./config.example.toml) 获取完整模板。 配置文件仅包含**地址和非机密标识符** —— 绝不包含 token 或密码。 ``` # ~/.config/ztb/config.toml(节选) [oidc] issuer = "https://accounts.google.com" client_id = "ztb-cli.apps.googleusercontent.com" callback_port = 8477 scopes = ["openid", "email", "profile"] [vault] addr = "https://vault.internal.example.com:8200" auth_mount = "oidc" role = "prod-operator" secret_path = "database/creds/prod-readonly" ttl = "15m" ca_cert = "/etc/ztb/vault-ca.pem" [boundary] addr = "https://boundary.internal.example.com:9200" auth_method_id = "amoidc_1234567890" default_scope = "global" ``` ### 环境变量 | 变量 | 用途 | | --- | --- | | `VAULT_ADDR` | Vault 地址(覆盖 `[vault].addr`)。 | | `BOUNDARY_ADDR` | Boundary controller 地址。 | | `ZTB_OIDC_ISSUER` | OIDC 签发者 URL。 | | `ZTB_OIDC_CLIENT_ID` | OIDC 公共客户端 ID(由 `ztb login` 使用)。 | | `RUST_LOG` | 日志过滤器(例如 `ztb=debug`);覆盖 `-v`。 | ## 快速开始 ### 前置条件 - **Rust** 1.74+ (`rustup`)。 - 一个 **OIDC provider**(例如 Google Workspace、Okta、Keycloak),并注册了一个用于环回重定向(`http://127.0.0.1:/callback`)的公共客户端。 - 一台启用了 JWT/OIDC auth method、配置了最小权限角色以及动态 secrets engine(数据库/SSH/PKI/…)的 **HashiCorp Vault** 服务器。 - 一个带有 OIDC auth method 且至少包含一个目标(最好配置了 Vault 凭证注入)的 **HashiCorp Boundary** controller + worker。 ### 构建与安装 ``` git clone https://github.com/panduraju50/zero-trust-boundary-vault-cli.git cd zero-trust-boundary-vault-cli # 构建 cargo build --release # 原地运行 ./target/release/ztb --help # 或者安装到 ~/.cargo/bin cargo install --path . ``` ### 首次运行 ``` mkdir -p ~/.config/ztb cp config.example.toml ~/.config/ztb/config.toml # 修改 issuer / client_id / vault 和 boundary 地址以匹配你的 env ztb login ztb connect ``` ## 安全考量 - **Token 存储。** OIDC token 和任何缓存的 Vault token 都存储在 OS keyring 中(macOS Keychain / Secret Service / Windows Credential Manager),**绝不**以明文文件或环境变量的形式存储。 - **PKCE (S256)。** CLI 是一个公共 OAuth 客户端。PKCE 将 token 交换绑定到初始请求,并消除了对 client secret 的任何需求。 - **State 与 nonce。** `state` 保护回调免受 CSRF 攻击;`nonce` 保护 ID token 免受重放攻击。在身份被信任之前,这两者都会被验证。 - **TLS 验证。** 始终强制执行。Vault CA 可以通过配置进行固定;不提供任何类似 `--insecure` 的绕过方式。 - **不记录凭证。** 机密材料被视为不透明数据,并从所有的 tracing/log 输出中进行脱敏处理。 - **会话拆除。** `ztb logout` 和正常的会话退出会主动撤销 Vault lease 并取消 Boundary 会话,在自动 TTL 过期的基础上将暴露窗口缩小至接近零。 - **设计上的最小权限。** 授权由已验证的 OIDC 声明驱动,并映射到范围严格的 Vault 角色和特定的 Boundary 目标。 ## 路线图 - [ ] 完善基于 JWKS 的 OIDC PKCE 环回流程和 ID token 验证。 - [ ] Vault JWT/OIDC 登录 + 动态 secret 签发(database/SSH/PKI 引擎)。 - [ ] Boundary 会话授权、代理和凭证注入。 - [ ] 由真实 keyring + controller 状态提供支持的 `status`/`whoami`。 - [ ] 拆除时显式的 lease 撤销和会话取消。 - [ ] 针对无头/跳板机环境的可选 device-code 流程。 - [ ] 面向 SIEM 摄取的结构化审计事件发射 (JSON)。 - [ ] 强化的配置验证和 CA pinning 测试。 - [ ] 针对开发模式 Vault + Boundary 的端到端集成测试。 ## 许可证 基于 [Apache License 2.0](./LICENSE) 授权。 ## 作者 **Panduranga Rajau M (Pandu)** — Senior SRE / DevSecOps,东京。CKS 持有者。 [GitHub](https://github.com/panduraju50) · [LinkedIn](https://www.linkedin.com/in/pandurangaraju/)
标签:HashiCorp Boundary, HashiCorp Vault, OIDC认证, Python安全, Rust, 动态密钥管理, 可视化界面, 网络流量审计, 运维工具, 通知系统, 零信任网络