Archived
110 lines
4.9 KiB
Markdown
110 lines
4.9 KiB
Markdown
# workload-sts
|
||
|
||
> **项目已停止开发。** 本方案已由 SPIRE 的 workload attestation、SPIFFE Workload API、
|
||
> JWT-SVID/X.509-SVID 和 OIDC Discovery Provider 替代。仓库仅保留设计与 PoC 历史,
|
||
> 不应部署或继续扩展。详见 [`docs/superseded-by-spire.md`](docs/superseded-by-spire.md)。
|
||
|
||
面向 workload identity 的 OAuth 2.0 Security Token Service。它验证 Kubernetes
|
||
ServiceAccount JWT 等上游身份,执行签发授权,并生成短期、限定 audience 的 JWT
|
||
assertion。
|
||
|
||
项目只负责“验证身份后签发 assertion”。OpenBao 等下游资源服务器自行验证 JWT、
|
||
映射本地权限并管理自己的 token、lease 和凭据生命周期。
|
||
|
||
项目在 PoC 阶段停止,未提供可运行服务或稳定 API。仓库中的 RFC 8693 与 OpenBao
|
||
Transit 代码只用于保存当时的技术验证,不构成受支持的软件。
|
||
|
||
## 目标
|
||
|
||
- 按 OAuth 2.0 Authorization Server 和 Token Exchange 标准语义提供接口,优先复用
|
||
成熟协议库。
|
||
- 第一阶段验证 Kubernetes projected ServiceAccount JWT,并为其他 credential issuer
|
||
保留独立 verifier 扩展点。
|
||
- 将已验证的上游身份映射为稳定的 workload principal。
|
||
- 根据 principal、audience、scope 和请求上下文判断是否允许签发,由服务端选择唯一的
|
||
token profile。
|
||
- 要求每个请求显式提交 `client_id`;v1 不认证该字段,只以 `client_id_claimed` 记录,
|
||
为以后注册 public/confidential client 保持稳定请求形状。
|
||
- `client_id` 长度为 3–63,只允许小写字母、数字和中横线,且必须以字母或数字开头和
|
||
结尾。
|
||
- 使用短期 JWT 隔离上游证明与下游访问凭据;一个 token 只面向明确的 audience。
|
||
- 让 OpenBao 保持机密、PKI、动态凭据和自身 token 生命周期的权威后端。
|
||
- 让 Kubernetes、OpenBao 和普通 OAuth2 Resource Server 使用各自的原生 JWT 验证
|
||
能力,而不要求业务系统理解上游身份来源。
|
||
- 提供结构化且不泄露 bearer token 的交换审计。
|
||
- 使用 OpenTelemetry trace/metric SDK 与标准 HTTP instrumentation,且不采集 token、
|
||
请求体或高基数身份字段。
|
||
|
||
## 非目标
|
||
|
||
- 不提供用户目录、密码登录、MFA 或交互式 OIDC 登录;人工身份由现有 IdP 提供。
|
||
- 不读取、缓存或代理 OpenBao 中的机密。
|
||
- 不替调用方登录 OpenBao,也不签发、续期或撤销调用方的 OpenBao client token;服务
|
||
自身可以使用独立的 Kubernetes identity 获取访问 Transit 所需的最小权限运行凭据。
|
||
- 不定义或同步 OpenBao policy、Kubernetes RBAC 或下游应用权限。
|
||
- 不管理 Gitea Actions job、runner、Kubernetes Pod、PVE VM 或 microVM 生命周期。
|
||
- 不实现 PVE/microVM vsock metadata service 或平台 attestation。
|
||
- 不自创策略表达式语言、workload identity 格式或私有 token exchange 协议。
|
||
- 第一阶段不直接返回 OpenBao token、SSH certificate、数据库密码或云凭据;以后增加
|
||
credential materializer 必须通过新的规格和安全评审。
|
||
|
||
## 核心流程
|
||
|
||
以 Kubernetes 中的 CI workload 登录 OpenBao 为例:
|
||
|
||
```text
|
||
CI Pod
|
||
|
|
||
| projected ServiceAccount JWT
|
||
| aud = https://identity.ad.ddupan.top
|
||
v
|
||
workload-sts
|
||
| 1. 验证 Kubernetes issuer、signature、audience 和时效
|
||
| 2. 映射 workload principal
|
||
| 3. 检查 OpenBao audience 的签发策略
|
||
| 4. 签发短期 JWT assertion
|
||
v
|
||
OpenBao JWT auth
|
||
| 验证 iss、sub、aud 和 bound claims
|
||
| 映射本地 role/policy
|
||
v
|
||
OpenBao client token
|
||
```
|
||
|
||
`workload-sts` 的职责在签发 JWT assertion 后结束。Bao token 的 TTL、renewal、
|
||
revocation、lease 以及 CI job 结束后的清理由 OpenBao 和调用方负责。
|
||
|
||
## 协议身份
|
||
|
||
当前设计使用:
|
||
|
||
```text
|
||
OAuth issuer: https://identity.ad.ddupan.top
|
||
```
|
||
|
||
OAuth issuer 是稳定的网络协议身份,不与进程部署位置绑定。SPIFFE 可以作为未来的上游
|
||
身份协议,但第一阶段不建立 SPIFFE trust domain,也不把内部 principal 伪装成 SPIFFE
|
||
ID。
|
||
|
||
## 文档
|
||
|
||
- SPIRE 替代决策:[`docs/superseded-by-spire.md`](docs/superseded-by-spire.md)
|
||
- 系统边界与数据流:[`docs/architecture.md`](docs/architecture.md)
|
||
- 规范行为与待决策项:[`docs/specification.md`](docs/specification.md)
|
||
- 威胁模型与安全要求:[`docs/security.md`](docs/security.md)
|
||
- 首轮库与签名 PoC 结论:[`docs/poc.md`](docs/poc.md)
|
||
|
||
其余文档均为替代决策前的历史材料,不再代表实施计划。
|
||
|
||
## 计划中的最小纵向切片
|
||
|
||
1. 发布 Authorization Server metadata 和 JWKS。
|
||
2. 验证一个 Kubernetes projected ServiceAccount JWT。
|
||
3. 按 RFC 8693 处理一次 token exchange。
|
||
4. 根据 SA binding 中的 issuance rule、请求 scope 和 CEL 条件决定是否签发。
|
||
5. 签发 `aud` 指向 OpenBao 的短期 JWT。
|
||
6. 由 OpenBao JWT auth 验证该 JWT 并返回受限 Bao token。
|
||
|
||
代码与发布物托管在
|
||
`git.ddupan.top/panxiao81/workload-sts`。
|