Claude Code 网关与用量
Claude Code 网关与用量
网关部署与运维
6 分钟阅读
Claude 应用网关的部署与运维
在 IdP 中注册网关、构建容器、部署到 Kubernetes 或 Cloud Run,并执行健康检查、密钥轮换、升级和安全管理等运维工作。
本页介绍运行 Claude 应用网关所涉及的运维工作:在身份提供商(IdP)中注册 OAuth 客户端、以容器形式部署网关,以及网关的日常运行维护。有关网关启动时读取的 gateway.yaml 文件中每个选项的说明,请参阅配置参考。
生产部署依次包含四个步骤,以下各节也按此顺序编排。前两个步骤需要你做出选择;后两个步骤则是网关运行后可供查阅的参考资料。
- 设置身份提供商:注册 OAuth 客户端,并查看 Okta、Entra 和 Google 各自的注意事项
- 部署网关:构建固定版本的容器镜像,并在 Kubernetes、Cloud Run 或你自己的平台上运行。本节还会介绍成本、绕过网关、多网关和 Serverless 方案的取舍
- 设置运维:日志、健康探针、中断期间的行为、密钥轮换和升级。设置监控和运维手册时可参考本节
- 审查安全状况:数据流向、威胁模型和合规问题解答。执行安全审查时可参考本节
如果登录或启动过程中出现故障,请直接前往故障排除,根据你看到的错误查找解决方案。
部署在专用网络中。 Claude Code 只会连接地址为私有地址的网关。这是一项安全防护措施,因为受信任的网关可以下发会在开发者计算机上运行命令的设置。请将网关置于内部负载均衡器或 VPN 之后,并为其配置一个仅解析到私有 IP 的主机名。
身份提供商设置
注册一个机密 OAuth/OpenID Connect(OIDC)Web 应用程序,设置唯一的重定向 URI https://<gateway>/oauth/callback,并将其分配给应当拥有网关访问权限的用户或用户组。
任何符合 OIDC 规范的 IdP 均可使用,包括 Okta、Microsoft Entra ID、Google Workspace、Keycloak、Dex、PingFederate 等。IdP 必须满足以下三项要求:
- 提供
/.well-known/openid-configuration;生产环境中须通过 HTTPS 提供。网关接受使用http://的签发者地址,但使用环回地址作为签发者时还须设置CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 - 支持授权码流程。PKCE(Proof Key for Code Exchange,授权码交换证明密钥)默认启用;对于不支持 PKCE 的 IdP,可通过
oidc.use_pkce: false将其禁用 - 在 id_token 中返回
email,并可选择返回groups;也可以在 userinfo 端点提供这些信息,同时设置oidc.userinfo_fallback: true
如果使用私有 PKI,请设置 oidc.ca_cert_pem。
部分提供商处理电子邮件和组声明的方式有所不同:
- Okta:位于
https://example.okta.com的组织授权服务器会返回精简的 id_token,其中不含email和groups。因此,将其用作issuer时,请始终设置oidc.userinfo_fallback: true。如果使用https://example.okta.com/oauth2/default之类的自定义授权服务器,并且该服务器在 id_token 中包含email和可选的groups,这些声明会直接发出,无需启用回退。只有在oidc.scopes中请求了groupsscope,且应用的组声明过滤器允许时,Okta 才会发出groups;如果未向 IdP 请求某项声明,userinfo_fallback也无法补全该声明。 - Microsoft Entra ID:
issuer=https://login.microsoftonline.com/<tenant-id>/v2.0。Entra 发出的是组的 Object ID,而非组名,因此请在managed.policies.match.groups中使用 GUID;也可以使用 App Roles 获得易于识别的名称。如果租户在roles而不是groups中发出角色,请设置oidc.groups_claim: roles。 - Google Workspace:
issuer=https://accounts.google.com。Google 的 id_token 不包含组信息。若要以 Google 作为 IdP,并使用基于组的allowed_groups或managed.policies,请配置oidc.google_groups。该配置会使用具有全域委派权限的服务账号,通过 Admin SDK Directory API 查询每位用户所属的组。若不使用此配置,请通过oidc.allowed_email_domains控制成员访问,并通过managed.policies.match.email_domain分配策略。Google 还会忽略标准的offline_accessscope。若要获取刷新 Token,请设置oidc.scopes: [openid, profile, email]和oidc.extra_auth_params: { access_type: offline, prompt: consent }。
如果使用的身份提供商未在上文列出,请参阅故障排除获取支持信息。
部署
网关是一个 Linux 二进制文件。由于副本无状态,且由 Postgres 充当共享协调层,因此网关可以横向扩展。你可以按照环境中运行其他无状态服务的方式来运行它。本节其余内容说明镜像所需的配置,并简要介绍 Kubernetes 和 Cloud Run 部署。
网关持有上游凭证,并充当推理流量的唯一出口,因此其设计目标是在你的网络内部运行。只要开发者和 IdP 能通过 HTTPS 访问,网关便可部署在任何位置;应当像对待其他持有生产凭证的服务一样对待它。
除部署位置之外,还需要考虑以下几项决策:
- 成本:网关没有单独的许可证费用或按席位收费;它是
claude二进制文件的一部分。你需要按照现有的云服务或 Anthropic 承诺用量支付推理费用,此外还要承担容器和遥测收集器的计算成本。 - 绕过网关:网关不会强制要求访问模型的唯一路径必须经过网关。持有自己凭证的开发者仍然可以直接调用提供商,因此是否关闭这条路径取决于网络策略。例如,可以阻止除网关之外的主机向
api.anthropic.com发出出站请求。但这样做也会使 WebFetch 域名安全检查失效,因为该检查会从每位开发者的计算机调用api.anthropic.com;请在托管策略中设置skipWebFetchPreflight: true将其禁用。 - 多个网关:每个网关都是一套独立部署,并有自己的配置。CLI 按网关主机名分别保存信任指纹和凭证,因此不同团队可以连接到不同网关,互不冲突。若要支持多个 OIDC 签发者,请分别运行不同实例。
- 无服务器平台:Cloud Run 可以运行网关;请设置
min-instances: 1,避免 OIDC 发现出现冷启动。Lambda 和 Cloud Functions 不适用,因为网关是一个长期运行的 HTTP 服务器。
这里介绍的每种生产拓扑都会在使用明文 HTTP 的副本之前放置 L7 代理,例如 Ingress、Cloud Run 前端或 ALB。请将 listen.trusted_proxies 设置为代理的源地址范围,使网关能够从 X-Forwarded-For 读取客户端 IP。网关仅在 TCP 对端受信任时才会接受该标头;Google Cloud 完整示例提供了不同拓扑对应的具体值。如果未配置受信任代理,所有请求看起来都来自代理 IP,这会使按 IP 限流退化成一个共享限流桶,并在审计事件中记录代理 IP。
容器镜像
以标准 Claude Code 版本中的原生 claude 二进制文件为基础,自行构建镜像:
- 从固定版本下载适合镜像架构的 Linux 构建;下载 URL 请参阅安装特定版本。
- 按照二进制文件完整性与代码签名中的说明,使用该版本经过 GPG 签名的
manifest.json验证构建。 - 将其复制到构建上下文中。
如果构建环境无法访问版本发布主机,请将该版本镜像到内部注册表,并固定设备群使用的版本。
除二进制文件外,镜像还需要:
- 基于 glibc 的镜像:glibc 构建唯一的动态依赖项是 glibc 库。基于 Musl 的镜像需要使用
linux-x64-musl或linux-arm64-musl构建,并安装其他软件包;请参阅 Alpine Linux 设置。 - 可写的状态目录:网关可以任意用户身份运行,但最小化镜像没有可写的主目录。请将
CLAUDE_CONFIG_DIR设置为/tmp/.claude等可写路径。 - 容器命令:
claude gateway --config /etc/claude/gateway.yaml。配置文件以只读方式挂载,密钥通过环境变量提供;网关监听listen.port,默认端口为8080。
Kubernetes
与其他无状态服务一样,以 Deployment 方式运行网关:
- 从 ConfigMap 挂载配置,从 Secret 挂载密钥;在 YAML 中通过
${file:/path/to/secret}或环境变量引用密钥 - 在 Ingress 处终止 TLS,并将
listen.public_url设置为 Ingress 主机名 - 将就绪探针指向
GET /readyz,存活探针指向GET /healthz
工作负载身份
优先使用平台的工作负载身份,而不是静态密钥:在 EKS 上为 Amazon Bedrock 和 Claude Platform on AWS 使用 IRSA;在 GKE 上为 Google Cloud's Agent Platform 使用 Workload Identity;在 AKS 上为 Microsoft Foundry 使用工作负载身份。在上游配置块中设置 auth: {};对于 Microsoft Foundry,则设置 use_azure_ad: true。随后,网关会通过相应提供商的默认凭证链获取 Pod 身份。对于跨云组合(例如在 GKE 上使用 Amazon Bedrock 上游),请改为在上游的 auth 配置块中设置显式凭证。upstreams 参考提供了各平台的设置详情。
Cloud Run
按以下方式配置服务:
- 保持
listen.port的默认值8080,该值与 Cloud Run 的默认PORT相符;也可以设置port: ${PORT} - 将
public_url设置为可从外部访问的源站地址。在生产环境中,这通常是内部负载均衡器的主机名,因为/login会拒绝公共地址,而*.run.appURL 会解析到公共地址。因此,单独使用 Cloud Run URL 只适合通过curl或浏览器进行冒烟测试。例外情况是:网络通过 Private Service Connect 和 Cloud DNS 专用区域将*.run.app解析为私有地址;在这种拓扑中,Cloud Run URL 可以作为有效的public_url。Google Cloud 完整示例涵盖了这两种方案。 - 以 Secret 卷的形式挂载配置
- 设置
min-instances: 1,避免首次请求时 OIDC 发现出现冷启动
如需一份完整的 Google Cloud 实践示例,其中涵盖 Cloud Run 或 GKE、Cloud SQL 和 Secret Manager,请参阅在 Google Cloud 上部署。
将网关 URL 下发到开发者计算机
网关开始提供服务后,通过托管设置将 forceLoginMethod 和 forceLoginGatewayUrl 下发到每位开发者的计算机。你可以使用 MDM,也可以直接写入各操作系统对应的 managed-settings.json。如果不这样做,/login 会显示标准账号选择器,其中没有网关选项。文件路径请参阅客户端托管设置。
运维
网关开始处理流量后,日常运维工作主要是读取日志、探测运行状况,以及按计划轮换密钥。以下小节逐一介绍这些工作,同时说明 Postgres 中保存的内容,以及升级和回滚的行为。
日志
网关会向 stderr 写入两类输出,两者都便于 JSON 处理:
- 审计事件:每个与安全相关的事件对应一行 JSON。请将 stderr 输送到日志聚合器。网关发出的事件包括
config.load、session.mint、session.refresh、device.authorize、device.verify、auth.denied、access.denied、inference、managed.serve、spend.blocked和admin.denied。字段会因事件而异:- 成功的创建与刷新事件包含
sub、email、client_ip以及结果 - 拒绝事件包含原因、路径和客户端 IP,因为发生拒绝时尚无身份信息
inference记录处理请求的上游及响应状态admin.denied记录被拒绝的管理 API 身份验证尝试,包括原因(invalid_key或no_credentials)、客户端 IP、方法和路径,但不会记录提交的密钥内容
- 成功的创建与刷新事件包含
- 运维日志:以
[gateway]为前缀的易读文本行,用于记录启动、警告和上游错误。环境变量CLAUDE_GATEWAY_LOG_LEVEL控制详细程度,可接受info、warn或error,默认为info。它不会影响审计事件,审计事件始终会发出。
健康检查
网关提供 GET /healthz 作为存活探针,并提供 GET /readyz 作为就绪探针;/readyz 会验证存储是否可访问。二者均不受 access_control.allow_cidrs 限制,因此即使监听器受到严格访问控制,探针仍可正常工作。
只有在配置加载、OIDC 发现、上游客户端构建和 Postgres 迁移全部成功后,位于 /.well-known/oauth-authorization-server 的 OAuth 发现文档才会返回 200,因此它也可以用作端到端启动检查。
运行中的网关还会在 <public_url>/protocol 提供其所接受的路径和请求格式说明,内容与当前运行的版本相对应。不同版本之间的内容并不稳定。
中断期间的行为
如果 Postgres 中断,网关本身仍会继续为已登录的开发者提供服务,但新登录会失败。开发者是否确实能继续工作,取决于编排器如何处理就绪状态:
- 现有会话:Bearer Token 通过 JWT 密钥在本地验证,会话刷新不访问存储,网关进程仍可处理推理
- 新登录:在 Postgres 恢复之前均会失败,因为设备流程及其限流计数器存储在 Postgres 中
- 消费限额执行:中断期间默认采用故障开放策略,因此推理仍可继续;如果你更希望阻断请求,而不是在无法计量时继续运行,可改用故障关闭策略
- 就绪状态:中断期间,
/readyz会报告未就绪,因此根据就绪状态控制流量的编排器会立即将所有副本从轮转中移除。在这种拓扑中,包括网关本可继续处理的推理请求在内,所有流量都会在负载均衡器处失败,直至 Postgres 恢复。/healthz存活探针仍会通过,因此副本不会重启。如果希望已登录开发者在存储中断期间继续工作,可改为将就绪探针指向/healthz;代价是新登录会被发送到仍报告就绪、但无法完成登录的副本。
如果 IdP 中断,现有会话可继续使用至 ttl_hours,但新登录和刷新会失败。如果 IdP 经常安排维护时段,请设置较长的 ttl_hours。
JWT 密钥轮换
按以下三个步骤轮换签名密钥,使现有会话保持有效:
- 生成新密钥,将其添加到
session.jwt_secret数组的最前面。 - 滚动部署。新 Token 使用新密钥签名,旧 Token 仍可通过验证。
- 等待
ttl_hours再加一段余量时间,然后删除旧密钥并再次滚动部署。
轮换也是让会话在到期前强制退出的唯一方法:Bearer Token 使用 JWT 密钥在本地验证,因此无法逐个撤销会话。如果直接替换密钥,而不在数组中保留旧密钥,所有尚未到期的会话都会立即失效。如果只是让个别用户离职停用,请在 IdP 中取消该用户的访问权限;其会话会在 ttl_hours 内结束。
Postgres
网关使用五张表,全部由启动时运行的迁移创建:
| 表 | 内容 | 保留期限 |
|---|---|---|
kv | 设备授权(TTL 为 10 分钟)和限流计数器 | 每行各自的 TTL |
spend | 每个主体在当前周期内的消费计数(单位为美分) | admin.spend_retention_months,默认为 13 |
spend_limits | 已配置的消费上限 | 直到通过 API 删除 |
admin_audit | 管理 API 变更记录 | admin.audit_retention_days,默认为 365 |
principal_emails | 每个主体最近一次出现时的电子邮件、显示名称和 IdP 组,包含个人身份信息(PII) | 自上次活动起经过 admin.identity_retention_days,默认为 90 |
每 30 秒运行一次的循环会清理超过 TTL 的 kv 行,每小时运行一次的清理任务会执行消费相关表的保留期限,因此不会有数据无限增长。如果未配置消费限额,则只会写入 kv。如果安全策略禁止应用角色执行 DDL,请使用管理员角色预先创建这些表及 _migrations,并向应用角色授予每张表的 SELECT, INSERT, UPDATE, DELETE 权限。
使用消费限额时,数据库丢失不仅会要求开发者重新登录,还会导致消费跟踪数据和上限丢失,因此请定期备份。如果要立即清除一位已离职开发者的数据,而不是等待保留期结束,请直接运行 DELETE FROM principal_emails WHERE principal = '<sub>';这会删除唯一保存其电子邮件、姓名和组信息的表中对应的数据。spend 和 admin_audit 行只引用经过假名化处理的 OIDC sub。
升级
副本无状态,因此随时进行滚动重启都是安全的。网关启动时会运行架构迁移,这意味着部署新二进制文件时会自动迁移数据库。如果数据库角色无法执行 DDL,请预先创建数据库架构,包括预置为当前版本的 _migrations 表;否则网关会因尝试执行 CREATE TABLE 而启动失败。
迁移只会追加,因此可以安全回滚到仅识别较少迁移的旧版二进制文件;旧版会忽略多出的行。回滚时还会根据旧版二进制文件的架构重新验证 YAML,因此,如果配置采用了新版引入的键,旧版会启动失败。请先删除新键,再执行回滚。
由于你在自己的镜像中固定了网关版本,只有更新固定版本并重新部署后,新版 Claude Code 中的修复(包括安全修复)才会进入部署。请按其他持有生产凭证的服务所采用的修补周期来更新网关。
安全
本节回答安全审查关注的问题:哪些数据流经网关以及流向何处、该设计可以防御哪些攻击,以及合规问卷中常见问题的答案。
数据流
| 数据 | 路径 | 网关是否发送到 Anthropic |
|---|---|---|
| 推理(Prompt、补全结果) | CLI → 网关 → 你的上游 | 仅当 Anthropic API 被配置为上游时 |
| 遥测(OTLP 指标,以及需选择启用的日志和跟踪) | CLI → 网关 → 你的收集器 | 从不 |
| 身份(电子邮件、组、sub) | IdP → 网关 → JWT → CLI;CLI 将其附加到 OTLP 导出数据中 | 从不 |
| 托管设置 | 你的网关 YAML → CLI | 从不 |
| 审计日志 | 网关 stderr → 你的聚合器 | 从不 |
威胁模型摘要
网关位于网络边界以内,但不会将每台开发者笔记本电脑视为可信设备。该设计通过以下三种方式应对这一点:
- 开发者持有的是短期 JWT,而非原始上游密钥。CLI 到网关这一段使用 RFC 8628 设备授权;网关与 IdP 之间的授权码交换在默认配置下使用 PKCE,因此截获的 IdP 授权码无法使用。
- 设备验证页面强制要求同源 POST,并按照 RFC 8628 §5.1 对每个 IP 实施限流。请参阅抵御用户代码暴力破解。
- 出站请求会经过服务器端请求伪造(SSRF)防护:该防护会解析 DNS,阻止链路本地地址、云元数据地址,并默认阻止环回地址;同时将连接固定到解析得到的 IP。因此,运营人员可影响的 URL(例如 IdP 和 OTLP 目标地址)无法被重定向到云元数据端点。RFC 1918 私有地址范围会被特意放行,因为 IdP 和 OTLP 收集器通常位于私有 IP 上。如果在本地开发环境中使用环回地址上的 IdP 或收集器,请在网关环境中设置
CLAUDE_GATEWAY_ALLOW_LOOPBACK=1;生产环境中不要设置。
如果自行添加出站流量控制,而网关使用工作负载身份等实例元数据凭证,则必须允许网关访问元数据服务器。
以下两类威胁不在网关的防护范围内,需要由你保护相应基础设施:
- 网关主机遭到入侵:主机既持有上游凭证,也向每位已连接的开发者分发托管设置,因此控制网关配置所带来的权限与控制 MDM 相当。CLI 会对能够执行 shell 命令的设置显示一次性批准对话框,这可以限制静默变更,但不能替代主机安全措施。
- 恶意 OIDC 提供商:提供商负责签署网关信任的 id_tokens,因此可以声明任意身份。你有责任审查并保护 IdP。
抵御用户代码暴力破解
开发者在 /device 验证页面输入的 user_code 由 20 个字符构成的字符集中选取 8 个字符,因此共有 20⁸(约 2.56×10¹⁰)种组合,并会在 10 分钟后过期。
网关会在设备授权端点上实施按 IP 限流,可通过 rate_limits 配置。如果许多开发者从同一个企业 NAT 地址登录,请提高限制。该限制仅适用于登录流程,不适用于推理。
合规状况
- 数据驻留:除非将 Anthropic API 配置为上游,否则网关自身的数据平面不会向 Anthropic 发送任何内容。如果配置了 Anthropic API,你现有的数据处理协议将适用于推理路径。遥测、审计、身份和设置数据只会发送到你配置的目标。
- 宿主进程流量:宿主进程是 Claude Code CLI,它可能会向 Anthropic 发送启动分析数据和更新检查请求。对于严格控制出站流量的部署,请在网关容器环境中设置
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1。 - 客户端分析:CLI 登录网关后会禁用自身的用量分析;在第三方 API 接口上,错误报告默认关闭。
- 客户端计算机:除非设置
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1和skipWebFetchPreflight: true,否则开发者的 CLI 仍会向 Anthropic 发送 WebFetch 主机名检查和版本检查。请参阅数据使用。 - 调查评分:网关凭证会禁用发往 Anthropic 的评分接收端,因此评分不会发送给 Anthropic。
- 对话记录共享:如果在调查的对话记录共享提示中选择 Yes,系统会在
~/.claude/feedback-bundles/下写入本地文件,而不是上传到 Anthropic。 - 客户端更新:更新检查独立于网关流量。请通过自己的分发机制固定版本;如果笔记本电脑不得获取新版本,请设置
DISABLE_UPDATES。DISABLE_AUTOUPDATER只会停止后台更新,claude update仍然可用。 - TLS:生产环境中应通过 HTTPS 提供
public_url。可以通过listen.tls使用网关自身的监听器,也可以在使用明文 HTTP 的副本之前放置终止 TLS 的 Ingress,并设置listen.public_url。网关不会拒绝明文 HTTP。生产环境中的 IdP 必须通过 HTTPS 提供服务,Postgres 支持?sslmode=require。请在 Ingress 处设置Strict-Transport-Security。 - 漏洞披露:请遵循报告安全问题中的说明
故障排除
如有问题或反馈,请使用 Claude Code 支持,或在 Claude Code GitHub 仓库中提交 issue。报告问题时,请提供:
- 网关问题:相关时间窗口内的网关 stderr、已隐去密钥的
gateway.yaml、网关版本(显示在/登录页面中,也可在/managed/settings响应的x-cc-gateway-version标头中查看),以及近期发生的变更 - 登录问题:让开发者运行
claude --debug-file ./claude-debug.txt,复现问题,然后发送该文件以及同一时间窗口内的网关审计日志 - 推理问题:请求的模型、已配置的上游,以及该请求对应的网关审计日志;日志会记录处理请求的上游和响应状态
| 症状 | 原因 | 解决方法 |
|---|---|---|
开发者的 /login 显示标准账号选择器,而不是 Cloud gateway 界面 | 该计算机的托管设置中未设置 forceLoginMethod 或 forceLoginGatewayUrl | 将托管设置文件部署到设备;/login 会从该文件读取网关 URL |
启动时显示 Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support. | 安装的 Claude Code 构建早于支持网关的版本 | 让开发者将 Claude Code 更新到包含 Cloud gateway 支持的版本 |
CLI /login:Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip> | 网关主机名至少解析到一个公共 IP 地址。Claude Code 会检查解析出的每个地址,并要求所有地址都是私有地址。常见原因是双栈名称中的某个地址族解析到了公共地址,其中包括 AWS 内部双栈负载均衡器,因为它会返回公共范围内的 AAAA 地址 | 确保在开发者计算机上,网关名称只解析到私有地址。对于双栈名称,请删除公共范围内的记录,或提供单独的仅限内部使用的 DNS 名称。请参阅专用网络前提条件 |
CLI /login:Gateway login requires a direct connection and does not support connecting through an HTTP proxy | HTTPS_PROXY 或 HTTP_PROXY 适用于网关主机,且代理主机名解析到公共地址。如果代理主机只解析到私有地址,则允许使用该代理,也不会触发此错误 | 在开发者计算机上将网关主机添加到 NO_PROXY,使其采用直接连接;也可以使用主机名解析到私有地址的代理 |
CLI /login:Could not resolve gateway host <host> | 计算机无法解析网关的内部 DNS 名称,通常是因为它未连接企业网络 | 让开发者连接到你的网络或 VPN,然后重试 /login |
启动时退出,并显示指向 store.postgres_url 的配置验证错误 | 未配置 Postgres;网关必须使用 Postgres | 设置 store.postgres_url。本地开发时可使用一次性容器:docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres。 |
启动时退出:requires the native binary | 当前通过 Node 运行,而不是原生二进制文件 | 使用任一独立安装方法安装 Claude Code |
启动时在 config.load 之后因 OIDC 发现错误而退出 | 无法访问 oidc.issuer,或 TLS 证书链不受信任 | 检查 Pod 能否访问签发者,以及签发者是否提供 /.well-known/openid-configuration。对于私有 PKI,请设置 ca_cert_pem。 |
| 启动时因 Postgres 权限错误而退出 | 应用角色缺少 CREATE TABLE 权限 | 使用管理员角色预先创建数据库架构,并向应用角色授予 DML 权限;也可以临时授予 DDL 权限,以便启动时应用新的迁移 |
/oauth/callback 显示 "Sign-in could not be completed" | 电子邮件域被拒绝、id_token 验证失败,或 email_verified 明确为 false;网关始终会拒绝后一种情况,无法覆盖此行为 | 检查 allowed_email_domains,并确认 IdP 返回经过验证的 email 声明。对于 email_verified: false,请在 IdP 端修复验证状态。如果 IdP 使用其他声明名称发出电子邮件,请设置 oidc.email_claim。 |
日志:token exchange failed: id_token missing email claim | IdP 默认未在 id_token 中包含 email。仅当设置了 allowed_email_domains 时才会触发此拒绝;如果未设置,缺少电子邮件的会话仍可创建 | 配置 IdP,使其在 id_token 中发出 email。Okta:将 email 添加到自定义授权服务器的 ID Token 声明中。Entra:在应用注册中将 email 添加为可选声明。PingFederate:启用会发出 email 的 OpenID Connect Policy。如果 IdP 只从 userinfo 端点提供 email,而不在 id_token 中包含该声明(例如 Okta 组织授权服务器),请设置 oidc.userinfo_fallback: true。 |
每个 Amazon Bedrock 请求都返回 502;日志显示 Could not load credentials from any providers | 在 EC2 上,IMDSv2 默认的跃点限制为 1,会阻止容器内部的实例元数据请求。启动和 /readyz 仍会通过,因为 AWS SDK 会在第一个请求到来时(而不是构建客户端时)解析实例凭证 | 使用 aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2 提高跃点限制,或在启动模板中设置。此变更会应用到实例上的每个容器。应优先使用 ECS 任务角色(如果可用);它通过 ECS 容器凭证端点读取凭证,可以完全避免此变更。也可以仅在专用网关实例上应用该变更,以缩小暴露范围。 |
| IdP 错误:scope 未知或不受支持 | IdP 拒绝无法识别的 scope | 将 oidc.scopes 设置为 IdP 接受的确切列表;其中必须包含 openid。默认值为 openid profile email offline_access。 |
设置 oidc.scopes 后,会话不再静默续期 | 覆盖配置中移除了 offline_access | 如果 IdP 支持,请重新添加 offline_access。没有刷新 Token 时,开发者需要每隔 session.ttl_hours 重新通过浏览器登录。 |
| 浏览器显示 "This request came from another site and was blocked" | 跨站表单 POST 被 CSRF 防护阻止;嵌入式或代理页面上会出现这一预期行为 | 直接打开验证链接 |
| Chrome 阻止 Approve 按钮并显示 "Refused to send form data … violates … Content Security Policy directive: form-action",但同一页面在 Safari 或 Firefox 中可以正常工作 | Chrome 会针对整个重定向链执行 form-action。IdP 继续重定向到另一个不在允许列表中的主机 | 将重定向链中的每个额外源站都添加到 oidc.form_action_origins。在 Approve 页面打开 Chrome DevTools → Console,查看被阻止的源站。 |
| 在 IdP 中完成登录后回调失败;Chrome 显示 CSP 错误,或 Safari 显示 "this sign-in link has expired" | IdP 通过 response_mode=form_post 返回授权码,该模式会以 POST 跨源自动提交到 /oauth/callback。Chrome 会在严格 CSP 下阻止此操作;Safari 允许提交,但回调只读取查询字符串 | 确保 IdP 遵循 response_mode=query;网关会显式请求该模式,使回调成为普通重定向 |
| 登录在本地可以正常工作,但位于 ALB 后方时失败 | 未设置 public_url,导致 IdP 将内部 http:// 源站用作 redirect_uri | 将 listen.public_url 设置为外部 https:// 源站 |
| 开发者反复看到信任提示 | TLS 证书在每个副本或每次请求之间轮换 | 在 Ingress 处使用稳定证书,或仅终止一次 TLS,并让副本在内部通过明文 HTTP 运行 |
CLI /login:"Could not verify the gateway's TLS certificate" 或 SELF_SIGNED_CERT_IN_CHAIN | 网关的 TLS 证书链由 CLI 主机信任存储中不存在的私有 CA 签名 | 原生二进制文件和 Node 22.15 或更高版本上的 Claude Code 默认读取操作系统信任存储;CLAUDE_CODE_CERT_STORE 控制此行为。如果 CA 已安装到操作系统信任存储,请确保开发者使用的是当前版本的运行时。否则,请在启动前将 NODE_EXTRA_CA_CERTS 设置为 CA 证书 PEM。首次连接时仍会显示指纹提示。 |
相关内容
- Claude 应用网关概览:快速入门和开发者连接方式
- 配置参考:
gateway.yaml的所有选项
桂公网安备45010502001169号