frozenprocess/telepathy
GitHub: frozenprocess/telepathy
Telepathy 是一款无需集群即可在 CI 中评估 Kubernetes 和 Calico 网络策略连通性的离线测试工具。
Stars: 1 | Forks: 0
# Telepathy
**在合并之前了解 NetworkPolicy 的作用 —— 无需集群。**
Telepathy 通过针对拓扑结构运行 [Calico](https://github.com/projectcalico) **自己的策略引擎** 来评估 Kubernetes 和 Calico NetworkPolicies。它可以在几毫秒内,无需 Kubernetes、无需 CNI、也无需节点的情况下,告诉你哪个 pod 可以与哪个 pod 进行通信。
因为它复用了 Felix(Calico 的大脑)的真实代码,而不是重新实现策略语义,因此其判定结果与你的集群实际执行的效果完全一致,Telepathy 甚至可以为你展示 Felix 针对相同策略会下发的 **iptables/nftables 链、eBPF 程序以及 Windows HNS ACL**。
## 用途
- **像测试代码一样测试你的策略** —— 断言 `frontend → backend = allow`、`attacker → backend = deny`,并在断言被破坏时让构建失败。
- **查看 PR 的影响范围** —— 一个 base 分支与 PR 分支的连通性差异对比,以评论的形式发布,展示该变更 *打开* 或 *关闭* 的每一个流量。
- **检查 dataplane** —— 无需集群即可渲染出策略编译后的实际 iptables/nftables/eBPF/HNS 规则。
## 快速开始
```
make build # clones the pinned Calico tree, builds bin/telepathy
make test # evaluate the sample topology + policy -> connectivity matrix
make verify # run the sample assertions (the CI gate)
make diff-demo # diff a base policy vs a PR that loosens it
```
该引擎是一个 stdin 到 stdout 的过滤器:输入一个拓扑 Request,输出一个 JSON 格式的连通性矩阵。
```
./bin/telepathy -policy testdata/sample-policy.yaml < testdata/sample-topology.yaml
```
```
{ "matrix": {
"demo/frontend->demo/backend": "allow",
"demo/attacker->demo/backend": "deny"
} }
```
## 三种模式
### 1. `evaluate`(默认) —— 连通性矩阵
探测特定 port/protocol 下的每一个有序 pod 对。只有当一对 pod 同时通过源端的 egress 和目的端的 ingress 时,才会判定为 `allow` —— 这与真实数据包必须通过的方式完全一致。
### 2. `test` —— 作为 CI gate 的断言
在你的策略旁边写下你的期望,让 Telepathy 去执行它们。当任何断言失败时,退出码将不为零。
```
# telepathy.tests.yaml
assertions:
- name: frontend may reach backend
from: demo/frontend
to: demo/backend
expect: allow
- name: attacker must not reach backend
from: demo/attacker
to: demo/backend
expect: deny # port/protocol optional — inherit the probe
```
```
telepathy test -assert telepathy.tests.yaml -policy ./policies < topology.yaml
# PASS frontend 可达 backend (demo/frontend -> demo/backend) expect=allow got=allow
# PASS attacker 不可达 backend (demo/attacker -> demo/backend) expect=deny got=deny
# 2 个通过,0 个失败
```
### 3. `diff` —— 这个变更打开或关闭了什么?
评估两个修订版本(例如两个 git checkout)上的矩阵,并仅报告发生移动的部分:
```
telepathy -policy ./policies < topology.yaml > base.json # on the base branch
telepathy -policy ./policies < topology.yaml > head.json # on the PR branch
telepathy diff -format markdown base.json head.json
```
生成 PR 评论如下:
`opened`(deny→allow)是一种新的暴露;`closed`(allow→deny)是一种可能的服务中断。使用 `-format json` 获取机器可读输出,或使用 `-exit-code` 在发生任何变化时判定为失败。
## 在 CI/CD 中使用
GitHub Action 封装了这两个 gate。在每一个 PR 上,它会运行你的断言,**并且**将 base 分支与 PR 分支的连通性差异对比作为一条置顶评论发布出来:
```
# .github/workflows/networkpolicy.yml
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
telepathy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # the diff needs git history
- uses: frozenprocess/telepathy@v1
with:
topology: path/to/topology.yaml
policy: path/to/policies/ # file or directory
assertions: path/to/telepathy.tests.yaml
```
有关所有输入参数,请参见 [`examples/github-actions.yml`](examples/github-actions.yml)。该引擎是 `scratch` 镜像中的一个单一静态二进制文件,因此任何运行容器的 CI(如 GitLab、Tekton、Argo、Jenkins)都可以用相同的方式调用它:
```
docker run --rm -i ghcr.io/frozenprocess/telepathy:latest \
test -assert /w/telepathy.tests.yaml -policy /w/policies < /w/topology.yaml
```
## 检查 dataplane
相同的 Request 可以渲染出 Felix 实际会下发的规则 —— 这是一个让你直观了解你的策略 *编译成什么* 的独特窗口:
```
telepathy iptables -policy p.yaml < topology.yaml # iptables / nftables chains
telepathy bpf -policy p.yaml < topology.yaml # annotated eBPF policy program
telepathy hns -policy p.yaml < topology.yaml # Windows HNS ACL rules
```
## 输入格式
一个 Request 由一个拓扑(`endpoints`、`namespaces`)加上一个探测(`port`、`protocol`)组成;策略通过 stdin 或 `-policy`(一个文件或包含多个 manifest 的目录)分层输入。支持 Kubernetes `networking.k8s.io/v1` NetworkPolicies 和 Calico `projectcalico.org/v3` (Global)NetworkPolicy、Tier、NetworkSet、HostEndpoint、Service/ServiceAccount 选择器等。有关最小化的端到端示例,请参见 [`testdata/`](testdata/)。
```
namespaces:
- { name: demo, labels: { kubernetes.io/metadata.name: demo } }
endpoints:
- { id: demo/frontend, namespace: demo, name: frontend, ip: 10.0.0.1, labels: { app: frontend } }
- { id: demo/backend, namespace: demo, name: backend, ip: 10.0.0.2, labels: { app: backend } }
- { id: demo/attacker, namespace: demo, name: attacker, ip: 10.0.0.3, labels: { app: attacker } }
port: 8080
protocol: tcp
```
## 工作原理
Telepathy 在各 CNI 之间是可插拔的。厂商中立的请求/响应 schema 位于轻量级的 [`api`](api/) 模块中,每个 CNI 的策略引擎都位于 [`provider`](provider/) 的 `Provider` 接口之后,并在运行时通过 `-provider` 进行选择(默认为 `calico`;`telepathy version` 会列出已注册的 provider)。这两种方式都是离线驱动 CNI 自己的代码 —— 无需集群。
至关重要的是,**每个 CNI 引擎都从其自己的 Go module 构建为独立的二进制文件**,因此它们的依赖关系图永远不需要相互妥协(Calico 和 Antrea 锁定了互不兼容的 `network-policy-api`、`controller-runtime` 等版本 —— 如果不进行版本 hack,将它们链接到一个二进制文件中是不可能的)。中立的 `api` JSON 契约就是它们之间的边界:
- **`calico`**([`provider/calico`](provider/calico/))被链接到主 `telepathy` 二进制文件中(基于 `third_party/calico` 构建):它根据你的拓扑和策略构建出一个 Felix `CalculationGraph`,通过 `app-policy/checker.Evaluate` 走查每一个有序对的 egress 和 ingress,并且可以渲染出 Felix 会下发的 iptables/nftables/eBPF/HNS dataplane。
- **`antrea`** 是一个独立的二进制文件,名为 `telepathy-engine-antrea`([`engines/antrea`](engines/antrea/),基于 `third_party/antrea` 并使用 Antrea 的原生依赖版本构建)。shell 会通过 JSON 契约将 `-provider antrea` 分发给它(stdin 上的 Request → stdout 上的 Response)。它驱动 Antrea 真实的 `grouping.GroupEntityIndex` 来解析 pod/namespace 选择器,然后对解析出的成员应用 Kubernetes NetworkPolicy 语义。跨进程测试会断言其结果与 Calico 引擎在流量层面完全一致。
`make build` 会同时生成这两个二进制文件;shell 会在其自身同级目录下寻找该引擎(可通过 `TELEPATHY_ANTREA_ENGINE` 覆盖)。
### 法律声明
上面使用的 Telepathy 卡牌图片是非官方的同人创作内容,根据同人内容政策 (Fan Content Policy) 获得许可。未经 Wizards of the Coast 批准或认可。所使用的部分素材版权归 Wizards of the Coast 所有。©Wizards of the Coast LLC。标签:Docker镜像, EVTX分析, 日志审计, 网络安全, 网络策略, 请求拦截, 隐私保护