You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Istio中subjectPeerCertificate等API是否仅在网关作为服务端生效?

问题

在Ingress和Egress网关中使用Lua过滤器,通过以下代码提取TLS握手时客户端与服务器的证书主题:

response_handle:headers():add("client-res", response_handle:connection():ssl():subjectLocalCertificate())
response_handle:headers():add("server-res", response_handle:connection():ssl():subjectPeerCertificate())

Ingress网关可成功提取两者的证书主题,但Egress网关提取失败,返回空请求头。经排查发现,当前提取的是Istio代理与Egress网关间MTLS使用的无主题证书,而非Egress网关与外部服务器间MTLS的证书主题。

疑问:response_handle:connection():ssl():subjectLocalCertificate()和response_handle:connection():ssl():subjectPeerCertificate()是否仅在网关作为服务端时生效,当网关作为客户端(Egress访问外部MTLS服务)时无法正常工作?

附使用的EnvoyFilter配置:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: example-namespace-envoy-filter
  namespace: example-namespace
  annotations:
    meta.helm.sh/release-name: example-namespace
    meta.helm.sh/release-namespace: example-namespace
  labels:
    app.kubernetes.io/managed-by: Helm
spec:
  workloadSelector:
    labels:
      istio: example-namespace-egressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value: # lua filter specification
        name: envoy.lua
        typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_response(response_handle)
                response_handle:logCritical("from response handle")
                response_handle:headers():add("server-res", response_handle:connection():ssl():subjectPeerCertificate())
                response_handle:headers():add("client-res", response_handle:connection():ssl():subjectLocalCertificate())
            end
            function envoy_on_request(request_handle)
                request_handle:logCritical("from request handle")
                request_handle:headers():add("server-req", request_handle:connection():ssl():subjectPeerCertificate())
                request_handle:headers():add("client-req", request_handle:connection():ssl():subjectLocalCertificate())
            end
解答

是的,你当前调用的connection():ssl()获取的是网关作为服务端时的连接(即Istio Sidecar与Egress网关之间的内部MTLS连接),而非网关作为客户端与外部服务的upstream连接,所以在Egress场景下拿到的是内部无主题证书,而非外部服务的证书。

原因分析

你的EnvoyFilter将Lua过滤器挂载到了Egress网关的入口HTTP连接管理器(对应接收Sidecar请求的Listener),这里的connection()对象指向的是Sidecar到Egress网关的连接,完全不涉及Egress网关与外部服务的TLS握手过程,自然无法获取外部服务的证书信息。

解决方案

要获取Egress网关与外部服务的TLS证书主题,需要使用Envoy Lua API的upstream_connection()方法,该方法专门用于获取网关作为客户端发起请求时与上游服务的连接。修改后的Lua代码如下:

function envoy_on_response(response_handle)
    response_handle:logCritical("from response handle")
    -- 获取Egress与外部服务的upstream连接
    local upstream_conn = response_handle:upstream_connection()
    if upstream_conn and upstream_conn:ssl() then
        -- 外部服务的证书主题(Peer为外部服务,Local为Egress用于对外的客户端证书)
        response_handle:headers():add("external-server-subject", upstream_conn:ssl():subjectPeerCertificate())
        response_handle:headers():add("egress-client-subject", upstream_conn:ssl():subjectLocalCertificate())
    end

    -- 可选:保留内部连接的证书信息用于对比
    local local_conn = response_handle:connection()
    if local_conn and local_conn:ssl() then
        response_handle:headers():add("internal-sidecar-subject", local_conn:ssl():subjectPeerCertificate())
        response_handle:headers():add("internal-egress-subject", local_conn:ssl():subjectLocalCertificate())
    end
end

function envoy_on_request(request_handle)
    request_handle:logCritical("from request handle")
    -- 注意:请求阶段upstream连接尚未建立,无法获取外部服务证书信息
    local local_conn = request_handle:connection()
    if local_conn and local_conn:ssl() then
        request_handle:headers():add("internal-sidecar-subject", local_conn:ssl():subjectPeerCertificate())
        request_handle:headers():add("internal-egress-subject", local_conn:ssl():subjectLocalCertificate())
    end
end

关键说明

  • upstream_connection()仅在envoy_on_response阶段可用,因为此时Egress网关已经与外部服务完成TLS握手并收到响应,upstream连接已建立。
  • connection()始终指向网关作为服务端时的客户端连接(即Sidecar到Egress的连接),无论Ingress还是Egress场景。

内容的提问来源于stack exchange,提问作者Priyansha Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:40:56