配置使用远程 JWKS 的 JWT 身份验证

借助 Cloud Service Mesh,您可以使用 Istio RequestAuthentication 自定义资源验证 JSON Web 令牌 (JWT),从而保护您的服务。此配置的关键部分是 jwksUri 字段,用于指定 JSON Web 密钥集 (JWKS) 提供方的 URI。此 JWKS 包含用于验证入站 JWT 的公钥。

重要提示:在 Cloud Service Mesh 中,数据平面(Envoy 代理)负责直接从 jwksUri 中提取 JWKS 密钥。Cloud Service Mesh 控制平面(由 Traffic Director 管理)不会进行外部调用来获取这些密钥。这意味着,与外部 JWKS 提供商的所有网络通信都源自工作负载的 Envoy 代理。

外部 JWKS 访问权限的前提条件

如需遵照本指南操作,您需要:

  • 互联网访问组织政策:如果您的 jwksUri 指向外部互联网端点,则您的 Google Cloud 组织政策必须允许工作负载的出站互联网访问。具体而言,请验证组织政策 constraints/compute.disableInternetNetworkEndpointGroup 是否未强制执行。如果此政策已启用,则从外部 jwksUri 中提取 JWKS 将会失败。

  • 带有标签的 Kubernetes 工作负载RequestAuthenticationAuthorizationPolicy 资源使用 selector 来定位特定工作负载。您必须在集群中运行工作负载(例如 Kubernetes 部署),且该工作负载具有政策可以匹配的标签。例如,httpbin 示例已配置为使用 app: httpbin 标签运行。您可以随意使用 Istio JWT 令牌指南中的 httpbincurl 设置。

启用 JWKS 获取功能的方法

您可以通过以下两种主要方式配置 Cloud Service Mesh,以允许 Envoy 代理从外部 jwksUri 中提取 JWKS 密钥:

这是大多数生产场景的推荐方法,对于使用 MCP 的 Cloud Service Mesh,此方法是必需的。此方法可让您明确控制网格与外部 JWKS 提供方的互动方式。

使用 ServiceEntry 定义外部服务

首先,您必须创建一个 Istio ServiceEntry,使外部 JWKS 提供方成为网格中的已知服务。此资源可为数据平面中的 Envoy 代理实现 DNS 解析和适当的路由。

对于使用 jwksUri: "https://your-auth-provider.com/.well-known/jwks.json"RequestAuthentication 政策,您将创建以下 ServiceEntry

apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: "external-jwks-provider-se"
  namespace: your-namespace 
spec:
  hosts:
  - "your-auth-provider.com" # Hostname from your jwksUri
  location: MESH_EXTERNAL
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: DNS

使用 DestinationRule 配置连接设置

其次,您可能需要 DestinationRule 来指定与 JWKS 提供方的连接的客户端 TLS 设置,尤其是在提供方需要特定的 TLS 或 mTLS 配置时。

  • 对于使用公开可信证书的提供方,请创建一个 DestinationRule,并将 tls.mode 设置为 SIMPLE,以启用标准服务器端 TLS 验证。
  • 对于需要客户端证书 (mTLS) 的提供方,请将 tls.mode 设置为 MUTUAL,并提供 Envoy 必须提供的证书和密钥的路径。

DestinationRule 会为上一步中定义的 ServiceEntry 配置连接政策:

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: "external-jwks-provider-dr"
  namespace: your-namespace 
spec:
  host: "your-auth-provider.com" # Must match a host in the ServiceEntry
  trafficPolicy:
    tls:
      # Use SIMPLE for standard server-side TLS.
      mode: SIMPLE 
      
      # If the JWKS provider uses a custom CA, provide the CA cert bundle.
      # caCertificates: /path/to/provider-ca-cert.pem

      # For providers requiring mTLS from Envoy, uncomment the following:
      # mode: MUTUAL
      # clientCertificate: /path/to/client-cert.pem
      # privateKey: /path/to/client-key.pem
      # caCertificates: /path/to/provider-ca-cert.pem

当这些资源存在且配置正确时,Envoy 会使用它们来建立安全连接并获取 JWKS 密钥。

2. Cloud Service Mesh(仅限 Traffic Director)的自动配置

如果 Cloud Service Mesh 在 RequestAuthentication 政策中找不到涵盖 HTTPS jwksUri 的主机名和端口的用户定义 ServiceEntry,它会自动配置必要的设置,以便 Envoy 获取 JWKS 密钥。这种自动化功能可简化常见场景的设置,在这些场景中,默认连接到 jwksUri (HTTPS,标准 TLS) 就足够了。

自动配置的条件:在以下情况下,系统会自动执行此行为:

  • 您正在使用 Cloud Service Mesh 和 Traffic Director。
  • jwksUri 使用 https 方案。
  • jwksUri 指向外部的非集群本地服务。
  • 没有可见ServiceEntry(考虑了 RequestAuthentication 政策的命名空间和 ServiceEntryexportTo 字段)已管理 jwksUri 的主机名和端口。

如果满足这些条件,您的 Envoy 代理将配置为提取 JWKS,而无需您为该 jwksUri 创建明确的 ServiceEntryDestinationRule 资源。

正在配置RequestAuthentication

无论使用哪种 JWKS 获取方法,您都可以使用 RequestAuthentication 政策定义 JWT 验证规则。

apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: "jwt-example"
  namespace: your-namespace # Replace with your application's namespace
spec:
  selector:
    matchLabels:
      app: your-app # Replace with your application's label (e.g. httpbin)
  jwtRules:
  - issuer: "testing@secure.istio.io"
    jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.26/security/tools/jwt/samples/jwks.json"

jwtRules 中的关键字段(如需了解完整详情,请参阅 Istio RequestAuthentication 文档):

  • issuer:JWT 的签发者。
  • jwksUri:提供方的公钥集 (JWKS) 的 HTTPS URI。
  • fromHeaders(可选):指定预期 JWT 所在的标头位置。
  • fromParams(可选):指定预期包含 JWT 的查询参数。
  • forwardOriginalToken(可选):如果为 true,则将原始令牌转发到上游服务。

使用 AuthorizationPolicy 强制执行 JWT 身份验证

如需拒绝缺少有效 JWT 的请求,您必须将 RequestAuthentication 政策与 AuthorizationPolicy 配对。以下政策仅允许向 your-app 工作负载发送请求,前提是这些请求提供来自指定签发者和正文的有效 JWT。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: "require-jwt-for-your-app"
 namespace: your-namespace # Replace with your application's namespace
spec:
 selector:
   matchLabels:
     app: your-app # Replace with your application's label (e.g. httpbin)
 action: ALLOW
 rules:
 - from:
   - source:
       # This principal is typically in the format "issuer/subject"
       requestPrincipals: ["testing@secure.istio.io/sub-from-jwt"] # Replace with the expected principal

如需查看有关在授权中使用 JWT 声明的更详细示例和使用场景,请参阅针对 JWT 令牌的 Istio 授权任务

后续步骤