Archived
508 lines
21 KiB
Markdown
508 lines
21 KiB
Markdown
# Workload STS 系统规格说明书
|
||
|
||
| 项目 | 内容 |
|
||
| --- | --- |
|
||
| 状态 | Approved |
|
||
| 版本 | v0.1 |
|
||
| 最后更新 | 2026-09-10 |
|
||
|
||
本文定义 workload-sts 的第一阶段外部合同、范围、安全边界和验收标准。内部包结构和
|
||
具体 OAuth2/JWT/HTTP 库不属于外部兼容性合同。
|
||
|
||
## 1. 背景
|
||
|
||
homelab 中的 Kubernetes workload、CI worker、长期主机以及未来的外部 attestation
|
||
系统使用不同的初始身份证明。OpenBao 能验证其中一部分身份并签发自己的 token,但
|
||
不应承担所有跨环境主体映射和 OAuth2 federation 语义。
|
||
|
||
workload-sts 在上游身份与下游资源服务器之间提供薄的 token exchange 层:验证来源、
|
||
规范化主体、执行签发策略并生成短期 JWT。OpenBao 继续作为机密、PKI、动态凭据和自身
|
||
token 生命周期的权威系统。
|
||
|
||
## 2. 目标
|
||
|
||
1. 提供符合标准 OAuth 2.0 语义的 Authorization Server metadata 与 token endpoint。
|
||
2. 实现 RFC 8693 Token Exchange 的最小可互操作子集。
|
||
3. 第一阶段支持 Kubernetes ServiceAccount JWT,并为其他 credential issuer 保留
|
||
verifier 扩展边界。
|
||
4. 将上游身份映射为稳定、不可由客户端选择的 workload principal。
|
||
5. 只为显式获准的 audience 和 scope 签发 JWT,由服务端选择唯一 token profile。
|
||
6. 使 OpenBao、Kubernetes 和普通 Resource Server 能用原生 JWT 能力完成后续认证。
|
||
7. 保持 HTTP 服务无本地状态,并记录不含 token 内容的结构化审计事件。
|
||
|
||
## 3. 非目标
|
||
|
||
1. 不实现用户密码、MFA、Authorization Code flow 或用户 consent。
|
||
2. 不成为 OpenBao API proxy,不读取或返回 secret。
|
||
3. 不签发或管理 OpenBao client token、lease、renewal 和 revocation。
|
||
4. 不定义 OpenBao policy、Kubernetes RBAC 或应用业务权限。
|
||
5. 不管理 workload、runner、Pod、VM 或 microVM 生命周期。
|
||
6. 不实现 PVE/microVM vsock metadata 和 attestation。
|
||
7. 不根据未经验证的 Gitea job 环境变量建立身份。
|
||
8. 不实现自定义策略解析器。
|
||
9. 第一阶段不支持任意第三方动态 client/issuer 注册。
|
||
10. 第一阶段不直接返回 OpenBao token、SSH certificate、数据库密码或云凭据;增加非
|
||
JWT credential materializer 必须进入新的规格版本和安全评审。
|
||
|
||
## 4. 参与者
|
||
|
||
| 参与者 | 职责 |
|
||
| --- | --- |
|
||
| Subject | 持有上游 credential 并请求 token exchange 的 workload |
|
||
| Credential issuer | 签发或证明 subject credential,并由对应 verifier 验证 |
|
||
| OAuth client | 调用 token endpoint 的软件;v1 的必填 `client_id` 是自报审计标签,不参与认证 |
|
||
| workload-sts | 验证、映射、授权并签发 JWT |
|
||
| Policy administrator | 配置 verifier、binding、audience、issuance rule 和 profile |
|
||
| Signing backend | 保管私钥并执行 JWT 签名;生产环境使用 OpenBao Transit |
|
||
| Resource Server | 验证输出 JWT 并执行本地授权,例如 OpenBao 或 Kubernetes |
|
||
|
||
## 5. 稳定标识
|
||
|
||
### 5.1 OAuth issuer
|
||
|
||
规范 issuer 为:
|
||
|
||
```text
|
||
https://identity.ad.ddupan.top
|
||
```
|
||
|
||
所有 metadata、JWKS 和 JWT `iss` 必须使用完全一致的 issuer。服务部署地址、Pod IP、
|
||
内部 Service DNS 和数据库位置不能进入 `iss`。
|
||
|
||
### 5.2 Principal
|
||
|
||
每个 principal 具有不可变 ID 和可读名称:
|
||
|
||
```text
|
||
id: <immutable identifier>
|
||
name: ci/homelab-infra-plan
|
||
```
|
||
|
||
输出 JWT 使用不可变 ID 作为 `sub`,可选的受控 claim 表示可读名称:
|
||
|
||
```json
|
||
{
|
||
"sub": "<immutable principal ID>",
|
||
"principal_name": "ci/homelab-infra-plan"
|
||
}
|
||
```
|
||
|
||
SPIFFE ID 只有在未来通过真正的 SVID verifier 验证后才作为 source subject 使用。内部
|
||
principal 不使用 `spiffe://` URI 模拟 SPIFFE 身份。
|
||
|
||
### 5.3 Audience
|
||
|
||
audience 是已登记资源服务器的稳定标识,不是任意用户输入。初始 OpenBao audience 为:
|
||
|
||
```text
|
||
https://bao.ad.ddupan.top:8200
|
||
```
|
||
|
||
每个 Kubernetes cluster 必须使用独立 audience。
|
||
|
||
## 6. OAuth 2.0 接口
|
||
|
||
### 6.1 Metadata
|
||
|
||
服务必须发布 RFC 8414 Authorization Server Metadata,至少公布:
|
||
|
||
- `issuer`;
|
||
- `token_endpoint`;
|
||
- `jwks_uri`;
|
||
- `grant_types_supported`;
|
||
- `token_endpoint_auth_methods_supported`;
|
||
- `scopes_supported`;
|
||
|
||
第一阶段的 `token_endpoint_auth_methods_supported` 只包含 `none`。
|
||
|
||
第一阶段不是 OIDC Provider,只发布:
|
||
|
||
```text
|
||
/.well-known/oauth-authorization-server
|
||
/oauth2/token
|
||
/oauth2/jwks
|
||
/healthz
|
||
/readyz
|
||
```
|
||
|
||
不发布 authorize、OIDC discovery、introspection 或 revocation endpoint。
|
||
|
||
### 6.2 Token Exchange 请求
|
||
|
||
服务必须接受表单编码的 RFC 8693 请求:
|
||
|
||
```http
|
||
POST /oauth2/token
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
|
||
&subject_token=...
|
||
&subject_token_type=urn:ietf:params:oauth:token-type:jwt
|
||
&requested_token_type=urn:ietf:params:oauth:token-type:access_token
|
||
&audience=https://bao.ad.ddupan.top:8200
|
||
&scope=bao.login
|
||
&client_id=homelab-infra-ci
|
||
```
|
||
|
||
第一阶段:
|
||
|
||
- `grant_type` 只接受 token exchange;
|
||
- `subject_token` 在第一阶段必填;
|
||
- `subject_token_type` 必须来自已支持集合;
|
||
- `requested_token_type` 只支持 access token;
|
||
- `audience` 必须且只能解析为一个已登记 audience;
|
||
- `resource`、`actor_token`、delegation 和 impersonation 暂不支持;
|
||
- `scope` 只能请求 grant 已允许集合的子集;
|
||
- `scope` 是保留的标准扩展点,第一阶段必须显式提交;
|
||
- `client_id` 必填且没有默认值,是调用方自报的有界审计标签,不注册、不认证且不参与
|
||
授权;
|
||
- 客户端不能提交 token profile、TTL、输出 claims、签名算法或 signing key;
|
||
- 不返回 refresh token。
|
||
|
||
第一阶段 token endpoint 不要求额外的 confidential client credential;调用者身份来自
|
||
经过验证的 `subject_token`。必填 `client_id` 只能以 `client_id_claimed` 语义进入审计,不能
|
||
作为已验证身份、授权输入或低基数 metric label。允许调用方自选 `client_id` 是本项目
|
||
刻意采用的审计语义,不代表完整 OAuth client registration;依赖已注册 client identity
|
||
的通用 OAuth 行为不在 v1 合同内。以后增加 mTLS 或 `private_key_jwt` client
|
||
authentication 必须保持 client identity 与 subject identity 分离。
|
||
|
||
缺少、为空或格式不合法的 `client_id` 返回 `invalid_request`,不推导匿名或默认 client。
|
||
未来启用 client registration/authentication 时继续使用同一必填字段,并将审计语义从
|
||
`client_id_claimed` 提升为经过验证的 client identity。
|
||
|
||
`client_id` 长度必须为 3–63,只允许 ASCII 小写字母、数字和中横线,且首尾必须是字母
|
||
或数字。规范正则表达式为:
|
||
|
||
```regex
|
||
^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])$
|
||
```
|
||
|
||
### 6.3 成功响应
|
||
|
||
成功响应使用标准 OAuth2 token response:
|
||
|
||
```json
|
||
{
|
||
"access_token": "<signed JWT>",
|
||
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
|
||
"token_type": "Bearer",
|
||
"expires_in": 300,
|
||
"scope": "bao.login"
|
||
}
|
||
```
|
||
|
||
响应必须带 `Cache-Control: no-store` 和 `Pragma: no-cache`。
|
||
|
||
### 6.4 错误响应
|
||
|
||
错误必须使用 OAuth2/RFC 8693 标准错误,例如:
|
||
|
||
- `invalid_request`;
|
||
- `invalid_grant`;
|
||
- `invalid_scope`;
|
||
- `unsupported_grant_type`;
|
||
- `invalid_target`。
|
||
|
||
响应不得暴露 token 内容、签名验证细节、内部 policy 表达式或数据库信息。认证失败与
|
||
授权失败的外部响应应避免成为主体和 grant 枚举接口。
|
||
|
||
## 7. 上游凭据验证
|
||
|
||
### 7.1 通用要求
|
||
|
||
所有 JWT verifier 必须校验:
|
||
|
||
- 配置的 issuer;
|
||
- 允许的签名算法;
|
||
- signature;
|
||
- `exp`、`nbf` 和允许的时钟偏差;
|
||
- 面向 workload-sts 的 audience;
|
||
- subject 存在且满足该 issuer 的格式合同。
|
||
|
||
discovery 与 JWKS 地址来自管理员配置,不能由请求动态提供。未知 issuer、`kid` 或算法
|
||
必须拒绝,且不能回退到不校验签名的模式。
|
||
|
||
### 7.2 Kubernetes ServiceAccount JWT
|
||
|
||
第一阶段必须支持 projected ServiceAccount JWT。每个 Kubernetes cluster 作为独立
|
||
verifier 配置,至少包含:
|
||
|
||
- cluster ID;
|
||
- issuer URL;
|
||
- workload-sts audience;
|
||
- TokenReview API 配置;
|
||
- 允许映射的 namespace 与 ServiceAccount。
|
||
|
||
第一阶段使用 TokenReview,并在 `spec.audiences` 显式提交 workload-sts audience;只有
|
||
`status.authenticated=true` 且 `status.audiences` 包含兼容 audience 时才验证成功。
|
||
TokenReview 失败或不可用时失败关闭,不自动降级为离线 JWKS。
|
||
|
||
### 7.3 未来 verifier
|
||
|
||
不同 credential issuer 使用不同 verifier 逻辑,并统一输出类型化的已验证身份。第一阶段
|
||
不实现 SPIFFE、通用 OIDC、云身份或 metadata issuer;增加它们不应改变 token endpoint
|
||
合同。
|
||
|
||
未来接入 SPIFFE 时必须使用真正的 SVID 语义:
|
||
|
||
- 验证 JWT-SVID trust bundle、audience 和时效;
|
||
- 通过已验证 mTLS 连接接受 X.509-SVID;
|
||
- 将 SPIFFE ID 作为 source subject,再显式映射到内部 principal;
|
||
- 不接受 HTTP header 或请求字段自报的 SPIFFE ID。
|
||
|
||
X.509-SVID 若作为 mTLS client authentication,预计使用 `client_credentials` 而不是
|
||
缺少 `subject_token` 的非标准 token exchange;该流程需单独规格批准。
|
||
|
||
## 8. Trust binding 与 principal
|
||
|
||
trust binding 使用以下输入匹配上游身份:
|
||
|
||
```text
|
||
credential type
|
||
upstream issuer/verifier ID
|
||
source subject
|
||
verified attributes
|
||
```
|
||
|
||
每个 binding 输出唯一规范化 principal,并携带该身份允许的 issuance rules。客户端不能
|
||
请求 principal,也不能让同一个未约束通配规则跨 issuer 匹配。credential
|
||
issuer/verifier 不是 OAuth client;自报 `client_id` 不参与 binding。
|
||
|
||
初始 Kubernetes 映射示例:
|
||
|
||
```yaml
|
||
verifier: k8s-homelab
|
||
sourceSubject: system:serviceaccount:ci:homelab-infra-plan
|
||
principalID: 01993f4d-5e1a-7000-8000-000000000001
|
||
principalName: ci/homelab-infra-plan
|
||
issuanceRules:
|
||
- audience: https://bao.ad.ddupan.top:8200
|
||
allowedScopes: [bao.login]
|
||
tokenProfile: openbao-login-jwt
|
||
```
|
||
|
||
配置模型最终采用文件、数据库 API 或管理 API 尚待决定。
|
||
|
||
## 9. 签发授权
|
||
|
||
### 9.1 结构化 issuance rule
|
||
|
||
binding 中的 issuance rule 至少关联:
|
||
|
||
```text
|
||
audience
|
||
allowed scopes
|
||
token profile
|
||
optional CEL condition
|
||
```
|
||
|
||
有效授权为已匹配 binding、issuance rule 和客户端请求的交集。客户端可以请求更少,
|
||
不能请求更多。服务端直接使用唯一匹配 rule 绑定的 token profile;零个匹配表示不允许
|
||
签发,多个匹配表示配置冲突并失败关闭。
|
||
|
||
### 9.2 CEL
|
||
|
||
项目使用现成 CEL 实现,不自行编写表达式解析器。CEL 只处理基于已验证事实的条件,
|
||
不能替代 principal、audience 和 scope 的结构化模型。
|
||
|
||
初始 CEL 环境计划提供:
|
||
|
||
```text
|
||
credential.type
|
||
credential.issuer
|
||
credential.subject
|
||
credential.attributes
|
||
principal.id
|
||
request.audience
|
||
request.scopes
|
||
```
|
||
|
||
token profile 是 binding/issuance rule 的配置,不作为 CEL 输入。具体类型、允许函数、
|
||
cost limit 和错误语义必须在实现前形成 API reference。CEL 编译或求值失败一律拒绝签发。
|
||
|
||
## 10. Token profile 与 JWT claims
|
||
|
||
token profile 由管理员定义,并由匹配当前 Kubernetes 身份的 binding/issuance rule 在
|
||
服务端确定。它至少限制:
|
||
|
||
- audience;
|
||
- 最大 TTL;
|
||
- 签名 key/algorithm;
|
||
- 允许 scopes;
|
||
- 固定 claims;
|
||
- 从 verified identity 派生的 claims 模板。
|
||
|
||
所有输出 JWT 必须包含:
|
||
|
||
```json
|
||
{
|
||
"iss": "https://identity.ad.ddupan.top",
|
||
"sub": "01993f4d-5e1a-7000-8000-000000000001",
|
||
"principal_name": "ci/homelab-infra-plan",
|
||
"aud": ["https://bao.ad.ddupan.top:8200"],
|
||
"iat": 1789062000,
|
||
"nbf": 1789062000,
|
||
"exp": 1789062300,
|
||
"jti": "<unique identifier>",
|
||
"scope": "bao.login"
|
||
}
|
||
```
|
||
|
||
客户端不能直接提供输出 claim map。面向 OpenBao 的 token 默认不携带 Bao policy 名;
|
||
OpenBao 应根据 `iss`、`sub`、`aud` 和必要的受控 profile claim 映射本地 JWT role。
|
||
|
||
第一阶段 JWT TTL 固定为五分钟,允许 30 秒时钟偏差。输出 token 不可续期且不附带
|
||
refresh token;客户端不能请求 TTL。这不约束资源服务器随后签发的本地 token。
|
||
|
||
## 11. 签名与 JWKS
|
||
|
||
生产环境通过 OpenBao Transit 完成签名,使 workload-sts 实例和数据库都不保存私钥。
|
||
workload-sts 使用自己的 Kubernetes ServiceAccount JWT 登录 OpenBao,取得只能访问指定
|
||
Transit signing key 和所需公钥信息的短期运行凭据。该凭据不是客户端通过 STS JWT
|
||
登录 OpenBao 后取得的 token。实现必须:
|
||
|
||
- 为 JWT 设置稳定 `kid`;
|
||
- 发布当前公钥及仍覆盖有效 token 的旧公钥;
|
||
- 只允许 token profile 选择的算法;
|
||
- 在签名后端不可用时失败关闭;
|
||
- 使轮换周期和旧公钥保留时间覆盖最大 JWT TTL 与允许时钟偏差。
|
||
|
||
第一阶段使用 RS256,Transit 使用 RSA key、SHA-256 和 PKCS#1 v1.5 签名。实现前的互操作
|
||
PoC 必须证明 Transit 生成的 JWS 能由项目 JWKS、OpenBao JWT auth 和 Kubernetes 外部
|
||
JWT authenticator 验证;PoC 失败则返回规格阶段重新选择算法。
|
||
|
||
## 12. 状态与数据库
|
||
|
||
实现使用 Go 1.26、PostgreSQL、`pgx/v5` 和版本化 migration。HTTP 实例必须无本地持久
|
||
状态,可在共享数据库之上水平扩展。数据库可以保存配置、策略版本和审计索引,但禁止
|
||
保存:
|
||
|
||
- subject token;
|
||
- 输出 JWT;
|
||
- Authorization header;
|
||
- OpenBao token;
|
||
- OAuth client secret 明文;
|
||
- JWT signing private key。
|
||
|
||
第一阶段不提供管理 API。声明式配置先离线校验,再通过独立 publish 命令在一个事务中
|
||
写入新的 policy version;HTTP 实例只读取已激活版本。配置写入必须具有版本和审计信息。
|
||
|
||
## 13. 审计与可观测性
|
||
|
||
每次 token exchange 至少产生:
|
||
|
||
```text
|
||
timestamp
|
||
request ID
|
||
credential verifier ID/type
|
||
upstream issuer
|
||
client_id_claimed(v1 必有,且明确标记为未经认证)
|
||
principal
|
||
audience
|
||
approved scopes/profile
|
||
policy version
|
||
allow/deny/error result
|
||
output jti(仅成功时)
|
||
```
|
||
|
||
审计不得记录任何完整 bearer token,也不得把 `client_id_claimed` 表述为已认证 client。
|
||
metrics 只能使用 verifier、audience、profile 和结果等受控低基数字段;不能把自报
|
||
`client_id`、subject、`jti` 或请求字符串作为 metric label。
|
||
|
||
## 14. 失败语义
|
||
|
||
- verifier、数据库、策略或签名后端不可用时失败关闭;
|
||
- 未知 issuer、principal、audience、scope 或 profile 均拒绝签发;
|
||
- CEL 编译/求值失败拒绝签发;
|
||
- 客户端断开和服务超时必须取消下游 discovery、JWKS、数据库及签名请求;
|
||
- 重试可能产生多个仍然有效的输出 JWT,因此资源服务器不能假定一次请求只有一个
|
||
`jti`;
|
||
- 内部错误对客户端返回稳定 OAuth2 错误,对日志记录无 token 的诊断原因。
|
||
|
||
## 15. 第一阶段验收标准
|
||
|
||
1. metadata 正确公布 issuer、token endpoint、JWKS 和支持的 grant/type。
|
||
2. 合法 Kubernetes projected SA JWT 可映射到唯一 workload principal。
|
||
3. 错误 issuer、signature、audience、算法、`exp` 或 `nbf` 的 JWT 被拒绝。
|
||
4. 未配置 trust binding、audience、scope 或 profile 的请求被拒绝。
|
||
5. 客户端请求超过 issuance rule 的 scope 时不能扩大权限,也不能提交 TTL。
|
||
6. CEL 条件只读取类型化的已验证事实;编译或求值错误拒绝签发。
|
||
7. 成功响应符合 RFC 8693,并带 `no-store`/`no-cache`。
|
||
8. 输出 JWT 具有正确 `iss`、`sub`、`aud`、时效、`jti` 和批准后的 scope。
|
||
9. OpenBao JWT auth 可以验证输出 JWT,并按自己的 role/policy 返回受限 client token。
|
||
10. workload-sts 不接收、记录、续期或撤销该 Bao token。
|
||
11. 面向 OpenBao 的 JWT 被配置为 Kubernetes audience 的验证器拒绝,反向亦然。
|
||
12. workload-sts 使用自己的 Kubernetes identity 取得最小权限 Bao token,并且只能调用
|
||
预期 Transit key;客户端的 Bao token 不经过 workload-sts。
|
||
13. 签名密钥轮换期间,旧的未过期 JWT 仍可通过 JWKS 验证。
|
||
14. 日志、错误、metrics、trace、数据库和测试 artifact 不含 canary token。
|
||
15. 两个服务实例共享数据库时,对相同配置产生一致授权结果和有效 JWT。
|
||
16. 客户端不能选择 token profile;同一身份、audience 和 scope 匹配多个 issuance rule
|
||
时拒绝签发。
|
||
17. 删除或禁用 trust binding 后不再签发新 token,已有 JWT 最迟在最大 TTL 后失效。
|
||
18. 每个请求必须显式提交合法 `client_id`,且没有默认值;v1 只将其作为
|
||
`client_id_claimed` 进入审计,改变它不改变
|
||
principal、issuance rule、profile、scope 或输出 claims。
|
||
|
||
## 16. 已确认决策
|
||
|
||
- 项目名称为 `workload-sts`。
|
||
- 使用标准 OAuth2 Token Exchange 语义,不设计私有 exchange 协议。
|
||
- 项目职责截止于验证身份、授权签发并生成 JWT assertion。
|
||
- OpenBao token 及其 TTL、renewal、revocation、lease 和应用清理由下游负责。
|
||
- OpenBao 保持机密、PKI、动态凭据和最终 policy 的权威后端。
|
||
- Kubernetes 可以作为上游 issuer,也可以原生验证 workload-sts 的外部 JWT;两个方向
|
||
使用不同 issuer、audience 和用途。
|
||
- `scope` 作为标准扩展点保留并由客户端显式提交;客户端不能选择 token profile。
|
||
- `client_id` 必填且没有默认值;v1 是调用方自报的审计标签,不注册、不认证且不参与
|
||
任何安全决策,未来 client authentication 继续复用同一字段。
|
||
- `client_id` 使用 3–63 字符的 DNS-label-like 小写字母、数字和中横线语法,中横线不能
|
||
位于首尾。
|
||
- 权限条件使用现成策略实现;第一阶段选择 CEL,不自行实现表达式解析器。
|
||
- 内部 principal 使用不可变 ID;SPIFFE 只有在验证真正 SVID 时才作为上游身份,不使用
|
||
`spiffe://` URI 模拟 SPIFFE 语义。
|
||
- PVE/microVM vsock metadata 与 attestation 由其他项目负责。
|
||
- Gitea Actions 运行于 Kubernetes 时使用 Kubernetes workload identity,运行于 VM 时
|
||
使用对应平台提供的标准 workload identity。
|
||
- 服务是无状态 HTTP 加数据库,部署位置不是协议或信任边界。
|
||
- OAuth issuer 使用 `https://identity.ad.ddupan.top`。
|
||
- 第一阶段只实现 Kubernetes projected ServiceAccount JWT verifier;其他 issuer 使用独立
|
||
verifier 扩展。
|
||
- workload-sts 使用自己的 Kubernetes ServiceAccount identity 获取最小权限 Bao 运行
|
||
token,以调用 OpenBao Transit 签名。
|
||
- 第一阶段只输出 JWT;直接返回其他凭据属于未来 credential materializer 的新规格。
|
||
- 第一阶段使用 Go 1.26、Kubernetes TokenReview、PostgreSQL、`pgx/v5`、UUIDv7
|
||
principal、五分钟 JWT TTL 和 30 秒时钟偏差。
|
||
- token profile 直接由匹配 Kubernetes 身份的 trust binding/issuance rule 确定。
|
||
- 第一阶段使用 OpenBao Transit RS256,并在实现前完成 JWKS、OpenBao 和 Kubernetes
|
||
外部 JWT authenticator 的互操作 PoC。
|
||
- 第一阶段只发布 RFC 8414 metadata、token、JWKS、healthz 和 readyz,不发布 OIDC、
|
||
authorize、introspection 或 revocation endpoint。
|
||
- 第一阶段不提供管理 API,声明式配置经独立命令校验后原子发布为数据库 policy version。
|
||
- 首轮 PoC 决定不采用 Fosite:v0.1 使用 Go 标准 HTTP/form 处理窄 RFC 8693 endpoint,
|
||
使用 `go-jose/v4` 做 JOSE/JWK 互操作,并通过官方 `openbao/api/v2` 调用 Transit。
|
||
- HTTP 路由层使用 `chi/v5`,保持 handler 和 middleware 与标准 `net/http` 兼容;OAuth
|
||
表单字段仍由协议层显式解析,不使用自动 request binding。
|
||
- 可选的可观测性使用 OpenTelemetry Go trace 与 metric SDK,启用时 HTTP server 使用
|
||
`otelhttp`;未配置 telemetry 时纯 chi handler 不创建 OTel instrumentation。SDK
|
||
exporter/reader 由进程启动配置注入,不在协议层固定 OTLP gRPC、OTLP HTTP 或具体后端。
|
||
第一阶段日志使用结构化日志并关联 trace/span ID,不要求启用 OpenTelemetry Logs SDK。
|
||
|
||
## 17. 待批准决策
|
||
|
||
- 基于已验证 principal 的限流策略;
|
||
- CEL 类型系统、cost limit 和策略发布流程;
|
||
- SPIFFE、通用 OIDC、云 workload identity 和外部 metadata issuer 的后续 verifier 合同;
|
||
- 非 JWT `requested_token_type` 与 credential materializer 的安全和响应合同。
|
||
|
||
## 18. 规范性参考
|
||
|
||
- [RFC 6749 — The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749)
|
||
- [RFC 7519 — JSON Web Token](https://www.rfc-editor.org/rfc/rfc7519)
|
||
- [RFC 8414 — OAuth 2.0 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414)
|
||
- [RFC 8693 — OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693)
|
||
- [RFC 9068 — JWT Profile for OAuth 2.0 Access Tokens](https://www.rfc-editor.org/rfc/rfc9068)
|
||
- [Kubernetes Service Accounts](https://kubernetes.io/docs/concepts/security/service-accounts/)
|
||
- [Kubernetes Authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
|
||
- [SPIFFE Concepts](https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/)
|