3. 流量拓扑概念

流量拓扑是服务网格安全基线的核心观测维度。在 Istio/Envoy 架构中,每一次服务间调用都包含明确的源(Source)、目标(Destination)、协议(Protocol)、端口(Port)、TLS 状态(mTLS)以及请求路径(Path)。理解这六要素,才能精确编写 OPA 策略来允许或拒绝特定流量。

3.1 流量拓扑六要素定义

要素 字段示例(Envoy/OPA) 说明
源(Source) source.principal / source.namespace 发起调用的工作负载身份(ServiceAccount)与命名空间
目标(Destination) destination.service.host / destination.workload 被调用的服务 FQDN 或工作负载标签
协议(Protocol) attributes.destination.protocol HTTP、gRPC、TCP、MongoDB 等应用层协议
端口(Port) destination.port 目标服务监听端口,如 8080、443、3306
TLS 状态 connection.mtls / connection.tls_version 是否启用双向 TLS、TLS 版本、加密套件
请求路径(Path) request.http.path HTTP 请求的 URI 路径,如 /api/v1/orders
安全基线要点:OPA 策略通常组合 source.namespace + destination.service.host + destination.port + connection.mtls 四个字段来定义一条允许规则。缺少任何一个字段都可能导致策略绕过或误拦截。

3.2 服务网格拓扑图:六要素可视化

下图展示了一个典型的微服务调用链,标注了从 frontend 到 orders 再到 payments 的完整流量拓扑六要素。

服务网格流量拓扑六要素示例 服务网格流量拓扑六要素示例 frontend ns: prod-front orders ns: prod-biz payments ns: prod-biz 请求1:frontend → orders 源: frontend (sa: frontend-sa) | 目标: orders.prod-biz.svc.cluster.local 协议: HTTP/1.1 | 端口: 8080 | TLS: mTLS (TLSv1.3, ECDHE-RSA) 路径: POST /api/v1/orders OPA策略: allow { source.ns == "prod-front"; dest.host == "orders"; port == 8080; mtls == true } 请求2:orders → payments 源: orders (sa: orders-sa) | 目标: payments.prod-biz.svc.cluster.local 协议: gRPC | 端口: 9090 | TLS: mTLS (TLSv1.3, ECDHE-RSA) 路径: /payment.v1.PaymentService/Charge OPA策略: allow { source.ns == "prod-biz"; dest.host == "payments"; port == 9090; mtls == true } 六要素安全基线 1. 源身份(ServiceAccount) 2. 目标服务(FQDN) 3. 应用层协议 4. 目标端口 5. mTLS 启用状态 6. HTTP 请求路径 缺失任一要素 → 策略盲区 → 可能导致安全绕过

3.3 请求路径与网格拓扑的层级关系

在服务网格中,请求路径(Path)是六要素中最细粒度的控制维度。一个完整的网格拓扑图通常包含三个层级:

  1. 集群层(Cluster):Kubernetes 集群边界,决定服务发现范围。
  2. 命名空间层(Namespace):逻辑隔离单元,OPA 策略常以 namespace 作为源/目标分组。
  3. 工作负载层(Workload):具体的 Pod/Service,携带 ServiceAccount 身份。
实践建议:在编写 Helm Chart 时,将流量拓扑六要素作为 values.yaml 的显式配置项暴露出来,例如:
# values.yaml
trafficTopology:
  - source:
      namespace: "prod-front"
      serviceAccount: "frontend-sa"
    destination:
      host: "orders.prod-biz.svc.cluster.local"
      port: 8080
      protocol: "HTTP"
    tls:
      mode: "STRICT"
    paths:
      - "/api/v1/orders"
      - "/api/v1/orders/*"
这样 OPA 策略可以通过 data.trafficTopology 动态生成规则,避免硬编码。

3.4 网格拓扑图:命名空间与工作负载视角

下图从命名空间隔离和工作负载身份两个维度,展示更完整的网格拓扑结构,突出 OPA 策略的生效范围。

命名空间与工作负载视角的网格拓扑 命名空间与工作负载视角的网格拓扑 Namespace: prod-front frontend sa: frontend-sa Namespace: prod-biz orders sa: orders-sa payments sa: payments-sa inventory sa: inventory-sa Namespace: prod-data mysql sa: mysql-sa redis sa: redis-sa OPA 策略生效范围:跨命名空间调用必须显式声明 source.namespace + destination.namespace + mTLS

3.5 六要素在 OPA 策略中的映射

在 OPA 的 input 文档中,Envoy 过滤器会将流量六要素映射为以下字段:

input = {
  "attributes": {
    "source": {
      "namespace": "prod-front",
      "principal": "spiffe://cluster.local/ns/prod-front/sa/frontend-sa"
    },
    "destination": {
      "service": {
        "host": "orders.prod-biz.svc.cluster.local",
        "name": "orders"
      },
      "port": 8080,
      "workload": {
        "labels": {"app": "orders", "version": "v2"}
      }
    },
    "request": {
      "http": {
        "method": "POST",
        "path": "/api/v1/orders",
        "host": "orders.prod-biz.svc.cluster.local:8080"
      }
    },
    "connection": {
      "mtls": true,
      "tls_version": "TLSv1.3"
    }
  }
}
常见陷阱:很多策略只检查 destination.service.host 和 destination.port,却忽略了 connection.mtls 状态。如果网格中某个服务意外降级为 PERMISSIVE 模式,未加密的明文流量可能绕过 mTLS 检查。务必在每条策略中显式断言 input.attributes.connection.mtls == true。

3.6 流量拓扑安全基线检查清单

检查项 OPA 断言示例 违规后果
源身份验证 source.principal == "spiffe://cluster.local/ns/prod-front/sa/frontend-sa" 未授权服务可发起调用
目标服务白名单 destination.service.host in ["orders.prod-biz.svc.cluster.local"] 流量被路由到恶意服务
端口限制 destination.port == 8080 绕过端口扫描防护
mTLS 强制 connection.mtls == true 明文流量泄露敏感数据
路径精确匹配 startswith(request.http.path, "/api/v1/orders") API 端点被未授权访问
协议一致性 attributes.destination.protocol == "HTTP" 协议混淆攻击