SPIFFE 是用于向工作负载颁发身份的 CNCF 标准。SPIRE 是其开源参考实现,此外还有多个商业产品也颁发符合 SPIFFE 规范的身份。Anthropic 可与任何发出 OIDC 兼容 JWT-SVID 的 SPIFFE 实现进行联合。有关当前的实现列表,请参阅 SPIFFE 项目网站上的实现 SPIFFE 的商业软件。
联合可以通过位于公共 HTTPS URL 的 OIDC 发现文档(discovery 模式,受 URL 约束限制)实现,也可以通过直接注册 JWKS(inline 模式)实现。
JWT-SVID 规范将 sub 定义为工作负载的 SPIFFE ID,并且 SPIFFE Workload API 要求调用方在获取时提供 aud,因此这些声明在各实现之间是相同的。Anthropic 还额外要求 iss 和 iat,而 JWT-SVID 规范并未强制要求这两者,因此请配置您的实现以填充这两个声明(在 SPIRE 中,iss 是 jwt_issuer 服务器设置,iat 会自动设置)。完成这些配置后,本指南的配置 Anthropic、获取并使用令牌和限定规则范围部分适用于任何 SPIFFE 实现。
SPIFFE 为每个工作负载分配一个形式为 spiffe://<trust-domain>/<path> 的稳定身份 URI,SPIRE 通过 Workload API 按需将该身份作为 JWT-SVID 颁发。JWT-SVID 是一个普通的已签名 JWT,其 sub 声明是工作负载的 SPIFFE ID,其 aud 声明由工作负载在获取时提供。
从 SPIRE 信任域到标准 OIDC 的桥梁是 SPIRE OIDC Discovery Provider,这是一个独立的辅助组件,用于发布 /.well-known/openid-configuration 以及信任域 JWT 签名密钥的 JWKS 端点。在发现提供程序运行的情况下,JWT-SVID 的验证方式与任何其他 OIDC 令牌相同:将发现 URL 注册为联合颁发者,编写一个匹配工作负载 SPIFFE ID 的联合规则,然后让工作负载将其 JWT-SVID 提交给 Anthropic 的令牌交换端点。
本页的示例使用 SPIRE,并适用于 SPIRE Agent 运行的任何地方:Kubernetes Pod、虚拟机和裸机主机。
如果您的 Kubernetes 集群未运行 SPIRE,而您希望改用集群原生的投射服务账号令牌进行认证,请参阅将 WIF 与 Kubernetes 结合使用。
inline 注册。iss 声明设置为您将注册为联合颁发者 issuer_url 的值。对于 discovery 模式,这是发现端点的公共 URL(在 SPIRE 中为 jwt_issuer 服务器设置)。获取 JWT-SVID 时要请求的受众(audience)值始终为 https://api.anthropic.com。请在 spiffe-helper 的 jwt_audience、Workload API 的 FetchJWTSVID 调用以及联合规则的 audience 匹配器中使用此值。
本节中的说明特定于 SPIRE。如果您使用其他 SPIFFE 颁发者,请根据其自身文档配置其 OIDC 发现端点和 JWT-SVID 获取方式,然后继续阅读配置 Anthropic。
如果您已经在运行带有 OIDC Discovery Provider 的 SPIRE,那么与 Anthropic 进行联合在 SPIRE 端需要三件事:与发现 URL 匹配的 jwt_issuer、将调用 Claude API 的工作负载的注册条目,以及让该工作负载获取带有 Anthropic 受众的 JWT-SVID 的方式。以下小节将逐一介绍。配置片段仅显示与 Anthropic 联合相关的设置,而非完整的 SPIRE 部署配置。
首次设置 SPIRE?请按照 SPIRE 快速入门部署 SPIRE Server 和 Agent,然后将 OIDC Discovery Provider 作为独立服务与 SPIRE Server 一起添加。发现模式的联合依赖于该提供程序已部署且可公开访问。该提供程序不是默认 SPIRE 安装的一部分。
Anthropic 通过将 JWT-SVID 的 iss 声明与已注册的联合颁发者进行匹配,并从该颁发者的发现文档中获取 JWKS 来验证 JWT-SVID。两个 SPIRE 设置必须使用相同的 URL:SPIRE Server 的 jwt_issuer(它会成为每个铸造的 JWT-SVID 中的 iss 声明)和 OIDC Discovery Provider 的 domains 列表(它决定了发现文档和 JWKS 的服务主机)。这个共享的 URL 就是您向 Anthropic 注册的内容。
信任域和颁发者 URL 是相互独立的。信任域(spiffe://prod.example.com)限定 sub 声明的范围。颁发者 URL(https://oidc-discovery.prod.example.com)是 Anthropic 获取签名密钥的位置。它们不需要共享主机名。
确认 SPIRE Server 的配置中已设置 jwt_issuer 并指向发现提供程序的公共 URL。以下示例还显示了默认的 JWT-SVID 生命周期。SPIRE 的内置默认值为 5 分钟,这个时间足够短,因此需要持续轮换(请参阅运行 spiffe-helper)。Anthropic 的令牌交换端点会拒绝任何生命周期超过联合颁发者配置的最大值的身份令牌,该最大值默认为 1 小时(请参阅验证规则)。此检查适用于所有 SPIFFE 实现,而不仅仅是 SPIRE,因此请将 default_jwt_svid_ttl(或任何按条目的覆盖值)保持在该最大值或以下。
server {
trust_domain = "prod.example.com"
jwt_issuer = "https://oidc-discovery.prod.example.com"
default_jwt_svid_ttl = "5m"
# ...
}在 OIDC Discovery Provider 的配置中,相同的主机名必须出现在 domains 下,并且该提供程序必须能够访问 SPIRE Server 的 API 套接字。该提供程序通过 HTTPS 提供发现文档和 JWKS。可以使用其内置的 ACME 支持来终止 TLS,或者在其前面放置一个执行 TLS 终止的负载均衡器。
domains = ["oidc-discovery.prod.example.com"]
server_api {
address = "unix:///run/spire/sockets/private/api.sock"
}
acme {
email = "[email protected]"
tos_accepted = true
}该示例使用 server_api,它将发现提供程序连接到 SPIRE Server 的特权 API 套接字。该提供程序还接受 workload_api 块(带有 socket_path 和 trust_domain),改为通过 SPIRE Agent 的 Workload API 获取信任包。当发现提供程序不应访问 Server API 或运行在无法访问 Server 的节点上时,请使用此方式。
每个调用 Claude API 的工作负载都需要一个 SPIRE 注册条目,将其运行时选择器映射到 SPIFFE ID。如果工作负载已注册,请记下其 SPIFFE ID,您将在联合规则的 subject_prefix 中使用它。如果尚未注册,请进行注册。对于 Kubernetes Pod,选择器通常是命名空间和 Kubernetes 服务账号:
# 将 NODE_UID 替换为节点的 UID:
# kubectl get node <node-name> -o jsonpath='{.metadata.uid}'
spire-server entry create \
-spiffeID spiffe://prod.example.com/ns/inference/sa/worker \
-parentID spiffe://prod.example.com/spire/agent/k8s_psat/prod-cluster/NODE_UID \
-selector k8s:ns:inference \
-selector k8s:sa:worker所示的 parentID 是单个节点自动生成的代理 ID。对于集群范围的注册,请将条目的父级设置为节点别名,使其匹配每个节点上的工作负载,就像 SPIRE Kubernetes 快速入门所做的那样。
Kubernetes 之外的工作负载使用主机级选择器,例如 unix:uid:1000(unix:path 也可用,但需要在代理的 unix 工作负载证明器配置中设置 discover_workload_path = true)。运行 spire-controller-manager 的集群可以使用 ClusterSPIFFEID 自定义资源声明条目,而不是直接调用 spire-server entry create。
spiffe-helper 是一个边车(sidecar)实用程序,它连接到 SPIRE Agent 套接字,为给定受众获取 JWT-SVID,将其写入文件,并在过期前重新获取。该辅助程序默认以守护进程模式运行。以下示例显式设置了 daemon_mode = true。
agent_address = "/run/spire/sockets/agent.sock"
# The JWT-SVID file is written under cert_dir
cert_dir = "/var/run/secrets/anthropic.com"
daemon_mode = true
jwt_svids = [{
jwt_audience = "https://api.anthropic.com"
jwt_svid_file_name = "token"
}]在 Kubernetes 中,将 spiffe-helper 作为边车容器运行,该容器与您的应用程序容器共享一个基于内存的 emptyDir 卷(medium: Memory),这样持有者 SVID 就永远不会落到节点的磁盘上。将主机上的 SPIRE Agent 套接字挂载到边车中,在两个容器中将共享卷挂载到 /var/run/secrets/anthropic.com,并在应用程序容器上设置 ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token。在虚拟机和裸机上,将 spiffe-helper 作为系统服务与工作负载一起运行,并将两者都指向一个共享目录。
在 Claude Console 中,打开 Settings → Workload identity,点击 Connect workload,然后选择 Custom OIDC。向导将引导您完成注册颁发者、创建服务账号和创建联合规则的过程。
向导会为您创建这些资源。无论您是在向导中输入这些值,还是将其发送到 Admin API,请使用以下值:
联合颁发者: 以 discovery 模式注册 OIDC Discovery Provider 的公共 URL。Anthropic 从此 URL 获取 /.well-known/openid-configuration,并跟随返回的 jwks_uri 来检索信任域的签名密钥。
{
"name": "spire-prod",
"issuer_url": "https://oidc-discovery.prod.example.com",
"jwks": { "type": "discovery" }
}如果发现提供程序无法从公共互联网访问,请自行获取 JWKS(curl https://oidc-discovery.prod.example.com/keys),并使用返回的 keys 数组的内容以 "jwks": {"type": "inline", "keys": [...]} 注册颁发者。在 inline 模式下,issuer_url 仅与 JWT-SVID 的 iss 声明进行比较。Anthropic 永远不会尝试访问它。
SPIRE 会频繁轮换 JWT 签名密钥,默认情况下与 CA 的轮换节奏相同(ca_ttl,24 小时)。如果您使用内联 JWKS 而不是发现 URL 注册颁发者,则必须在 SPIRE 每次轮换时更新 JWKS:在工作负载开始使用新密钥之前添加新密钥,并在使用旧密钥签名的令牌过期后移除被取代的密钥。留在内联 JWKS 中的过时密钥将无限期地保持受信任状态。
要在不暴露公共发现端点的情况下自动更新 JWKS,请配置 SPIRE Server 的 BundlePublisher 插件(aws_s3、gcp_cloudstorage 或 k8s_configmap),并设置 format = "jwks",以便在每次轮换时将 JWT 签名密钥推送到外部存储,然后通过 Admin API 更新颁发者的内联密钥。
联合规则: 匹配 JWT-SVID 的 sub(即 SPIFFE ID)以及您配置 spiffe-helper 请求的 aud。SPIFFE ID 是 URI 字符串,subject_prefix 将它们作为不透明文本进行匹配,因此精确值或带尾部 * 的前缀匹配都适用。对于更复杂的模式,请使用 CEL condition。
{
"name": "spire-inference-worker",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "spiffe://prod.example.com/ns/inference/sa/worker",
"audience": "https://api.anthropic.com"
},
"target": {
"type": "service_account",
"service_account_id": "svac_..."
},
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}token_lifetime_seconds 是交换返回的 Anthropic 访问令牌的生命周期,而不是 JWT-SVID 的生命周期。SDK 会自动刷新访问令牌。
请尽可能具体地限定工作负载。仅当注册在该路径下的每个工作负载都应映射到同一个 Anthropic 服务账号时,才将 subject_prefix 放宽为 spiffe://prod.example.com/ns/inference/*。将规则的 fdrl_... ID 添加到工作负载的 ANTHROPIC_FEDERATION_RULE_ID 环境变量中。
Anthropic SDK 可以从 spiffe-helper 维护的文件中读取 JWT-SVID,也可以通过令牌提供程序可调用对象直接调用 SPIFFE Workload API。文件路径是最简单的集成方式,适用于所有 SDK 语言。可调用对象方式无需边车,但需要您的应用程序语言中有 SPIFFE Workload API 客户端。
当 spiffe-helper 将新的 JWT-SVID 写入 /var/run/secrets/anthropic.com/token 时,将 ANTHROPIC_IDENTITY_TOKEN_FILE 设置为该路径,同时设置 ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 和 ANTHROPIC_WORKSPACE_ID。SDK 在每次令牌交换时都会读取该文件,因此它始终会获取最近轮换的 SVID,并在 Anthropic 访问令牌过期前自动刷新。有关每个值的来源,请参阅环境变量。
import anthropic
# 读取 spiffe-helper 写入到
# ANTHROPIC_IDENTITY_TOKEN_FILE 的 JWT-SVID,以及 ANTHROPIC_FEDERATION_RULE_ID、
# ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 和 ANTHROPIC_WORKSPACE_ID。
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))在接入 SDK 之前,直接从 SPIRE Agent 获取 JWT-SVID,并确认其声明与您的联合规则所期望的内容匹配。如果您使用其他 SPIFFE 实现,请使用其 CLI 或 Workload API 客户端获取 JWT-SVID,并以相同方式解码载荷。
Workload API 会对调用进程进行证明。对于 Kubernetes 注册条目,请在满足该条目选择器且已挂载代理套接字的 Pod 内运行此命令(例如,使用 kubectl exec)。在虚拟机和裸机上,请以匹配该条目 unix: 选择器的用户或进程身份运行。从未经证明的主机 shell 运行会返回 no identity issued,这是验证步骤中最常见的失败原因。
spire-agent api fetch jwt \
-audience https://api.anthropic.com \
-socketPath /run/spire/sockets/agent.sock \
-output json \
| jq -r '.[0].svids[0].svid' \
| jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'-output json 标志将 SVID 响应和信任包响应作为一个包含两个元素的 JSON 数组返回,因此 jq -r '.[0].svids[0].svid' 可以提取出纯令牌。在没有 -output 的较旧 SPIRE 版本上,该命令会打印一个带标签的块。在这种情况下,请将默认输出通过管道传递给 awk '/^[[:space:]]*eyJ/{print $1; exit}' 来提取令牌行。检查 iss 是否为您注册的 OIDC Discovery Provider URL,sub 是否为工作负载的 SPIFFE ID,以及 aud 是否包含 https://api.anthropic.com。然后运行获取并使用令牌中的 cURL 示例。成功的交换会返回以 sk-ant-oat01- 开头的 access_token。如果出现 400 invalid_grant,请参阅排查失败的交换。SPIRE 端最常见的原因是 SPIRE Server 的 jwt_issuer 与注册为联合颁发者的 URL 不匹配。
SPIFFE ID 路径约定由运维人员定义,因此联合规则的 subject_prefix 匹配器应反映您的注册条目使用的路径方案。常见方案包括 spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>(spire-controller-manager 中 ClusterSPIFFEID 资源发出的默认值)以及用于虚拟机和裸机工作负载的 spiffe://<trust-domain>/host/<hostname>/<service>。
subject_prefix 为 spiffe://prod.example.com/* 会匹配信任域中的每个工作负载。如果没有 audience 匹配器,该规则还会接受为任何受众铸造的 JWT-SVID,包括工作负载为无关的依赖方请求的那些。
将规则的 match 块锁定到适合您用例的最窄范围:
subject_prefix 设置为完整的 SPIFFE ID,不带尾部 *。audience,并使用相同的值配置 spiffe-helper(或 Workload API 调用),以便拒绝为其他依赖方铸造的 SVID。spiffe://prod.example.com/ns/inference/* 授权注册在某个命名空间下的每个工作负载,并为每个命名空间创建单独的规则和 Anthropic 服务账号,而不是扩大单个规则的范围。使用 Workload Identity Federation 将 Okta 服务应用程序身份联合到 Claude API。
使用来自您自己的身份提供商的短期身份令牌(而非长期静态 API 密钥)将工作负载认证到 Claude API。
Workload Identity Federation 的环境变量、验证规则、配置文件配置和错误参考。
使用投射服务账号令牌从自管理的 Kubernetes 集群认证到 Claude API。
Was this page helpful?