DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Vault Kubernetes 登录失败:检查 audience 与 TokenReview

Vault Kubernetes 登录失败时,分别检查应用 JWT、reviewer JWT、受众和 TokenReview 权限,核对本地令牌轮换与配置恢复条件。

应用向 Vault 的 Kubernetes 认证入口提交 ServiceAccount JWT,却得到登录失败;Vault 日志出现 login unauthorized 或 service account unauthorized。先区分两次请求:应用用 JWT 登录 Vault,Vault 还要以某个身份调用 Kubernetes 的 TokenReview API,核验这份 JWT。

应用令牌可以满足 Vault 的受众要求,却不一定适合拿来访问 Kubernetes API。若把同一份令牌同时用于这两个用途,受众或权限不匹配就可能阻断登录。令牌到期、账户或绑定关系变化也需要分别核对,不能把所有认证失败都归因于 audience。

先确认出错的是哪一层

记录实际 Vault 版本、Kubernetes auth 插件版本、认证挂载路径、应用使用的 ServiceAccount 和命名空间,再查看失败时的 Vault 日志与 Kubernetes API 返回结果。下面示例假设认证挂载为 kubernetes、Vault role 为 app-reader;按实际名称替换。

使用已有的、获准读取认证配置的 Vault 管理身份检查:

vault read auth/kubernetes/config
vault read auth/kubernetes/role/app-reader

检查 role 的 bound_service_account_names、bound_service_account_namespaces 与 audience,确认没有把 Kubernetes ServiceAccount 名称、Vault role 名称和应用命名空间混为一谈。

读取 config 不会返回 reviewer 的完整凭据。当前接口的 token_reviewer_jwt_set 可以提示是否配置了固定 reviewer JWT;看不到 token_reviewer_jwt 的值,不代表未配置。还要结合 Vault 是否运行在 Pod 内,以及 disable_local_ca_jwt 的值判断实际模式。

来自 Kubernetes API 的 401 Unauthorized 通常先查其调用者的令牌认证;已认证账户请求 TokenReview 得到 403 Forbidden 时,再查授权。Vault 对应用返回的状态和文字不一定等于内部 Kubernetes 请求的状态,不能只凭最外层一条错误定根因。

即使 Kubernetes API 接受了请求,TokenReview 响应仍可能是 status.authenticated=false,并带有 status.error。此时核对被审查的应用 JWT、请求中的受众,以及令牌期限、撤销和账户状态;它与 reviewer 请求被拒绝是不同的结果,新增权限绑定不能让一份无效令牌变得有效。

应用 JWT 与 reviewer JWT 各自要满足什么条件

应用 JWT 是交给 Vault 的登录材料,其受众须满足 Vault role 的要求,账户和命名空间也须匹配 role 的限制。reviewer JWT 则作为 Vault 访问 Kubernetes API 的凭据,既要能被该 API 接受,也要具有创建 TokenReview 的权限。

在获准处理令牌的本地终端,可只查看必要的 claims。下面示例用隐藏输入读取 JWT,不把完整令牌写进命令行参数或日志:

import base64
import json
from getpass import getpass

token = getpass("JWT (hidden): ")
parts = token.split(".")
if len(parts) != 3:
    raise ValueError("Expected a JWT with three segments")

part = parts[1]
payload = json.loads(base64.urlsafe_b64decode(part + "=" * (-len(part) % 4)))
for name in ("aud", "iss", "sub", "exp"):
    print(name, payload.get(name))

这只解码 payload,没有验证签名,也不证明令牌有效。aud 可能是字符串或数组;结合接收方配置核对,不能假定一律是固定的 vault。exp 与实际时间、sub 对应的账户以及令牌是否已被撤销,也要检查。claims 仍可能包含内部身份和地址,不粘贴到公开工单,更不把令牌上传到在线解码网站。

如果 ServiceAccount 显示 0 Secrets,先按TokenRequest 与 Pod 投射令牌的用法取得适合用途的令牌。恢复旧式长期 Secret 不应成为默认修复。

Vault 在 Pod 内时,优先核对本地 reviewer

Vault 1.9.3 及以后支持重新读取 Pod 中的本地 ServiceAccount token,以适应短期令牌轮换。使用这种模式前,确认 Vault 容器确实能读取本地 token 与 CA,且其 ServiceAccount 有所需的认证委派权限。更早的版本可能只读取一次,令牌到期后仍会失败。

下面是受限场景的配置示例:Vault 在 Kubernetes Pod 内,已选择默认挂载的本地 CA 和 token,没有需要保留的自定义 PEM、issuer 或其他附加配置。地址只是集群内示例,必须替换为现有已核验的 Kubernetes API 地址:

vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443" \
  token_reviewer_jwt="" \
  disable_local_ca_jwt=false

不要把这段当作所有现有认证挂载的局部补丁。配置更新的具体语义取决于所用插件版本;写入前记录完整配置、凭据的安全恢复来源和 role 设置,已有定制参数必须按该版本接口完整保留。写后重新读取配置,核对 host、CA 使用方式和 token_reviewer_jwt_set,再确认 Vault 实际使用的 reviewer 身份。

如果选择用应用 JWT 自身充当 reviewer,Vault 在 Pod 内时还涉及 disable_local_ca_jwt=true;每个应用账户都必须能调用 TokenReview,而该 JWT 的受众也必须被 Kubernetes API 接受。仅适合 Vault 登录的受众不一定满足后一条件,不应靠清空 Vault role 的 audience 来掩盖这个区别。

权限检查必须针对实际 reviewer

下面假设 reviewer 是 vault-system 命名空间中的 vault ServiceAccount。执行者需有相应 impersonation 权限;替换身份前先确认配置模式:

kubectl auth can-i create tokenreviews.authentication.k8s.io \
  --as=system:serviceaccount:vault-system:vault

这个命令检查 RBAC,不验证实际 reviewer JWT 的签名、受众或期限。若检查本身因 impersonation 权限不足而失败,不能据此断定 reviewer 无权调用 API。

确认缺少认证委派权限,且已获准修改集群授权时,可为该确切账户绑定 system:auth-delegator。下面的绑定名称须是本次新增且未占用的名称,不覆盖现有绑定:

kubectl create clusterrolebinding vault-tokenreview \
  --clusterrole=system:auth-delegator \
  --serviceaccount=vault-system:vault

不要改绑 cluster-admin,也不要为了省事绑定全部 ServiceAccount。若实际采用应用 JWT 作为 reviewer,检查和授权的主体应是相应应用账户,不能仍套用这里的 Vault 账户。

验证登录与轮换,保留恢复方式

用实际应用所用的账户、受众和认证挂载重新登录,确认返回的 Vault 身份与策略符合预期。登录成功后再核对所需 secret 的访问权限;Vault policy 拒绝读取 secret,与 Kubernetes TokenReview 失败是不同环节。

继续观察应用和 reviewer 令牌轮换后的登录。首次成功不证明固定短期 reviewer JWT 会自动续期,也不证明应用已重新读取投射令牌文件。

如果需要回退,按保存的完整配置和安全凭据来源恢复原认证模式。只有确认本次新建的 vault-tokenreview 绑定不再需要、也未被其他流程接管时,才单独撤销它:

kubectl delete clusterrolebinding vault-tokenreview

撤销会立即影响依赖该授权的认证请求。不要删除原有绑定,也不要通过关闭 TLS 校验、扩大全部权限或取消受众约束来让错误暂时消失。